[NOI2009]变换序列

Description

Input

Output

Sample Input

5
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 } 

 

posted @ 2018-03-18 18:54  Z-Y-Y-S  阅读(318)  评论(0编辑  收藏  举报