BZOJ1562 [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。
正解:二分图匹配
解题报告:
今天考试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 }
本文作者:ljh2000
作者博客:http://www.cnblogs.com/ljh2000-jump/
转载请注明出处,侵权必究,保留最终解释权!