​http://www.elijahqi.win/archives/1141​​​
题目描述

对于N个整数0,1,…,N-1,一个变换序列T可以将i变成Ti,其中:Ti∈{0,1,…,N-1}且 {Ti}={0,1,…,N-1}。 x,y∈{0,1,…,N-1},定义x和y之间的距离D(x,y)=min{|x-y|,N-|x-y|}。给定每个i和Ti之间的距离D(i,Ti),你需要求出一个满足要求的变换序列T。如果有多个满足条件的序列,输出其中字典序最小的一个。 说明:对于两个变换序列S和T,如果存在p

#include<cstdio>
#include<algorithm>
#include<cstring>
#define N 11000
using namespace std;
inline char gc(){
static char now[1<<16], *S, *T;
if(S==T){T=(S=now)+fread(now, 1, 1<<16, stdin); if(S==T)return EOF;}
return *S++;
}
inline int read(){
int x=0;char ch=gc();
while (ch<'0'||ch>'9') ch=gc();
while (ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=gc();}
return x;
}
struct node{
int y,next;
}data[N<<1];
bool used[N];
int n,girl[N],boy[N],h[N],d[N],num;
bool find(int x){
for (int i=h[x];i;i=data[i].next){
int y=data[i].y;if (used[y]) continue;used[y]=true;

if (!girl[y]||find(girl[y])){
boy[x]=y;girl[y]=x;return true;
}
}
return false;
}
int main(){
freopen("1963.in","r",stdin);
n=read();
for (int i=0;i<n;++i) d[i]=read();
for (int i=n-1;i>=0;--i){
data[++num].y=((i-d[i])%n+n)%n;data[num].next=h[i];h[i]=num;
data[++num].y=((i+d[i])%n+n)%n;data[num].next=h[i];h[i]=num;
if (data[num].y>data[num-1].y) swap(data[num].y,data[num-1].y);
}
//for(int i=1;i<=num;i+=2) printf("%d %d\n",data[i].y,data[i+1].y);
for (int i=n-1;i>=0;--i){
memset(used,0,sizeof(used));if (!find(i)) {
printf("No Answer");return 0;
}
}
for (int i=0;i<n-1;++i) printf("%d,boy[i]);printf("%d",boy[n-1]);
return 0;
}