BZOJ1562 [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。

 

 

正解:二分图匹配

解题报告:

  今天考试T2,考场上几乎想出正解,结果拍WA了就没管了。

  我们考虑倒着做,所以每次加入最优的的那条边,那么后面每次替换肯定是靠前的对字典序的贡献大。  

 

 1 //It is made by jump~
 2 #include <iostream>
 3 #include <cstdlib>
 4 #include <cstring>
 5 #include <cstdio>
 6 #include <cmath>
 7 #include <algorithm>
 8 #include <ctime>
 9 #include <vector>
10 #include <queue>
11 #include <map>
12 #include <set>
13 using namespace std;
14 typedef long long LL;
15 const int MAXN = 40011;
16 const int MAXM = 80011;
17 int n,a[MAXN],ecnt;
18 int w[MAXN][3];
19 int vis[MAXN],match[MAXN],ans[MAXN];
20 bool ok;
21 int first[MAXN],to[MAXM],next[MAXM];
22 
23 inline int getint()
24 {
25        int w=0,q=0; char c=getchar();
26        while((c<'0' || c>'9') && c!='-') c=getchar(); if(c=='-') q=1,c=getchar(); 
27        while (c>='0' && c<='9') w=w*10+c-'0', c=getchar(); return q ? -w : w;
28 }
29 inline bool dfs(int x,int o){
30     if(vis[x]==o) return false;   vis[x]=o; 
31     for(int i=1;i<3;i++) {
32     int v=w[x][i]; if(vis[v]==o) continue;    
33     if(!match[v] || dfs(match[v],o)) {
34         match[v]=x; match[x]=v;
35         return true;
36     }    
37     }
38     return false;
39 }
40 
41 inline void work(){
42     n=getint(); for(int i=0;i<n;i++) a[i]=getint();    
43     for(int i=0;i<n;i++) {
44     w[i][1]=i-a[i]; if(w[i][1]<0) w[i][1]+=n;
45     w[i][2]=i+a[i]; if(w[i][2]>=n) w[i][2]-=n;
46     if(w[i][1]>w[i][2]) swap(w[i][1],w[i][2]);
47     w[i][1]+=n; w[i][2]+=n;
48     }
49     ok=true;
50     for(int i=n-1;i>=0;i--) {
51     if(!dfs(i,i+1)) { 
52         ok=false; 
53         break; 
54     }
55     }
56     if(!ok) { printf("No Answer"); return ; }
57     printf("%d",match[0]-n); for(int i=1;i<n;i++) printf(" %d",match[i]-n);
58 }
59 
60 int main()
61 {
62   work();
63   return 0;
64 }

 

posted @ 2016-09-23 15:16  ljh_2000  阅读(291)  评论(0编辑  收藏  举报