BZOJ 1562: [NOI2009]变换序列 【二分图匹配】【匈牙利】

来源:互联网 发布:打击电信网络诈骗视频 编辑:程序博客网 时间:2024/06/07 08:28

Description

img

题解

显然,这就是二分图匹配字典序最小的解。

代码

#include<cstdio>#include<cstring>#include<algorithm>#define maxn 20006using namespace std;inline char nc(){    static char buf[100000],*i=buf,*j=buf;    return i==j&&(j=(i=buf)+fread(buf,1,100000,stdin),i==j)?EOF:*i++;}inline int _read(){    char ch=nc();int sum=0;    while(!(ch>='0'&&ch<='9'))ch=nc();    while(ch>='0'&&ch<='9')sum=sum*10+ch-48,ch=nc();    return sum;}int n,tot,sum,p[5],ans[maxn],mat[maxn],lnk[maxn],son[maxn],nxt[maxn];bool vis[maxn];void add(int x,int y){    nxt[++tot]=lnk[x];son[tot]=y;lnk[x]=tot;}bool dfs(int x){    if(!vis[x])return 0;    vis[x]=0;    for(int j=lnk[x];j;j=nxt[j]) if(mat[son[j]]==-1||dfs(mat[son[j]])){        mat[son[j]]=x;return 1;    }    return 0;} void hungary(){    memset(mat,255,sizeof(mat));    for(int i=n-1;i>=0;i--){        memset(vis,1,sizeof(vis));        sum+=dfs(i);    }}int _abs(int x){return x>0?x:-x;}int get(int x,int y){return min(_abs(x-y),n-_abs(x-y));}bool cmp(int x,int y){return x>y;}int main(){    freopen("distance.in","r",stdin);    freopen("distance.out","w",stdout);    n=_read();    for(int i=0;i<n;i++){        int x=_read();p[1]=i-x,p[2]=i+x,p[3]=i+x-n,p[4]=i+n-x;        sort(p+1,p+5,cmp);        for(int j=1;j<=4;j++)if(p[j]>=0&&p[j]<n&&get(i,p[j])==x)add(i,p[j]+n);    }    hungary();    if(sum<n)return printf("No Answer\n"),0;    for(int i=n;i<2*n;i++)ans[mat[i]]=i-n;    for(int i=0;i<n-1;i++)printf("%d ",ans[i]);printf("%d\n",ans[n-1]);    return 0;}
阅读全文
0 0
原创粉丝点击