[NOI2009]变换序列
Description
Input
Output
Sample Input
5
1 1 2 2 1
1 1 2 2 1
Sample Output
1 2 4 0 3
HINT
30%的数据中N≤50;
60%的数据中N≤500;
100%的数据中N≤10000。
二分图匹配
匈牙利算法的原理是冲突时替换
不过要求字典序最小,一个点会连出2条边,加边先加入大的,这样在匹配时就会先匹配小的
不过这是针对于链式前向星
然后如果i和j都匹配了T,且i<j
那么显然i配T更好,因为如果不这样i就要配一个更大的
所以要从后往前枚举
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 #include<algorithm> 6 using namespace std; 7 struct Node 8 { 9 int next,to; 10 }edge[50001]; 11 int match[20001],head[20001],num,n,vis[20001],sum,ans[20001]; 12 void add(int u,int v) 13 { 14 num++; 15 edge[num].next=head[u]; 16 head[u]=num; 17 edge[num].to=v; 18 } 19 bool dfs(int x) 20 {int i; 21 for (i=head[x];i;i=edge[i].next) 22 { 23 int v=edge[i].to; 24 if (vis[v]==0) 25 { 26 vis[v]=1; 27 if (match[v]==-1||dfs(match[v])) 28 { 29 ans[x]=v;match[v]=x; 30 return 1; 31 } 32 } 33 } 34 return 0; 35 } 36 int main() 37 {int i,x,v1,v2; 38 cin>>n; 39 memset(match,-1,sizeof(match)); 40 for (i=0;i<n;i++) 41 { 42 scanf("%d",&x); 43 v1=i-x;v2=i+x; 44 if (v1<0) v1+=n; 45 if (v2>=n) v2-=n; 46 if (v1<v2) swap(v1,v2); 47 add(i,v1);add(i,v2); 48 } 49 for (i=n-1;i>=0;i--) 50 { 51 memset(vis,0,sizeof(vis)); 52 if (dfs(i)) sum++; 53 else break; 54 } 55 if (sum<n) 56 { 57 cout<<"No Answer\n"; 58 return 0; 59 } 60 for (i=0;i<n-1;i++) 61 printf("%d ",ans[i]); 62 cout<<ans[n-1]; 63 }