bzoj 1562: [NOI2009]变换序列

来源:互联网 发布:大学生网络兼职 编辑:程序博客网 时间:2024/06/05 05:50

题意;

语文不好,概括不出,大概就是一个数可以用另两个数替换,求最小字典序答案。

题解:

有点玄学的增广路。
tyb的方法
容易想到二分图匹配,但是匹配要求字典序最小,一开始想到在建边的时候改变顺序,但是后来发现一个问题,前面已匹配的有可能会被后面的抢走,这样字典序就变大了。看了hzwer的代码,发现只要倒序匹配就好了,为什么呢?tkj大神告诉我,这样就能让前面的抢后面的,保证字典序最小。
code:

#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>using namespace std;int n,d[10010];struct node{    int y,next;}a[40010];int last[10010],len=0;void ins(int x,int y){    a[++len].y=y;    a[len].next=last[x];last[x]=len;}int chw[10010],match[10010],tim=0;bool findma(int x){    for(int i=last[x];i!=-1;i=a[i].next)    {        int y=a[i].y;        if(chw[y]!=tim)        {            chw[y]=tim;            if(match[y]==-1||findma(match[y]))                return match[y]=x,true;        }    }    return false;}int main(){    memset(last,-1,sizeof(last));    memset(match,-1,sizeof(match));    scanf("%d",&n);    for(int i=0;i<n;i++)    {        int tmp[5],k=0;        scanf("%d",&d[i]);        if(i>=d[i]) tmp[++k]=i-d[i];        if(i+d[i]<n) tmp[++k]=i+d[i];        int t=n-d[i];        if(i>=t) tmp[++k]=i-t;        if(i+t<n) tmp[++k]=i+t;        sort(tmp+1,tmp+1+k);        for(int j=k;j;j--) ins(i,tmp[j]);    }    for(int i=n-1;i>=0;i--)    {        tim++;        if(!findma(i)){printf("No Answer");return 0;}    }    int primt[10010];    for(int i=0;i<n;i++) primt[match[i]]=i;    for(int i=0;i<n-1;i++) printf("%d ",primt[i]);    printf("%d\n",primt[n-1]);}
原创粉丝点击