bzoj1562 [NOI2009]变换序列

bzoj1562 [NOI2009]变换序列


NOI也有SB题系列。
一个(i)只有两种可能的(T_i)
要求所有(T_i)不重复,且字典序坠小。
仔细想一想匈牙利匹配的过程就可以知道:要从后往前寻找匹配&优先匹配小的(T)
匈牙利秒之。

// It is made by XZZ
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define rep(a,b,c) for(rg int a=b;a<=c;a++)
#define drep(a,b,c) for(rg int a=b;a>=c;a--)
#define il inline
#define rg register
#define vd void
typedef long long ll;
il int gi(){
    rg int x=0;bool flg=0;rg char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')flg=1;ch=getchar();}
    while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    return flg?-x:x;
}
const int maxn=10001;
int A[maxn],B[maxn];
int match[maxn];bool vis[maxn];
il bool dfs(int x){
    if(!vis[A[x]]){
        vis[A[x]]=1;
        if(match[A[x]]==-1||dfs(match[A[x]])){
           match[A[x]]=x;
           return 1;
        }
    }
    if(!vis[B[x]]){
        vis[B[x]]=1;
        if(match[B[x]]==-1||dfs(match[B[x]])){
            match[B[x]]=x;
            return 1;
        }
    }
    return 0;
}
int T[maxn];
int main(){
    int n=gi(),d;
    rep(i,0,n-1){
        d=gi(),A[i]=(i+d)%n,B[i]=(i-d+n)%n;
        if(A[i]>B[i])swap(A[i],B[i]);
    }
    memset(match,-1,sizeof match);
    drep(i,n-1,0){
        memset(vis,0,sizeof vis);
        if(!dfs(i)){puts("No Answer");return 0;}
    }
    rep(i,0,n-1)T[match[i]]=i;
    rep(i,0,n-1)printf("%d ",T[i]);
    puts("");
    return 0;
}
原文地址:https://www.cnblogs.com/xzz_233/p/7608499.html