BZOJ 1562 [NOI2009]變換序列:二分圖匹配
阿新 • • 發佈:2018-02-10
ostream i++ log 滿足 code pos 要求 兩個 spa
題目鏈接:http://www.lydsy.com/JudgeOnline/problem.php?id=1562
題意:
給定n,定義D(x,y) = min(|x-y|, n-|x-y|),然後給定數組d[i] = D(i,T[i])。
讓你求一個0到n-1的排列T,下標i∈[0,n-1],滿足給定的D(i,T[i]),且字典序最小。
若沒有答案輸出"No Answer"。
題解:
其實就是讓你求一個排列T,其中T[i]要麽填(i+d[i])%n,要麽填(i-d[i]+n)%n。
所以對於每個i,向它能填的兩個數連邊,跑一邊最大匹配即可。
又因為要求字典序最小,所以對於每個i連邊時,應先連向較小的那個數。然後跑匈牙利的時候按從n-1到0的順序跑即可。
AC Code:
1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 #include <vector> 5 #define MAX_N 10005 6 7 using namespace std; 8 9 int n; 10 int d[MAX_N]; 11 int vis[MAX_N]; 12 int mat[MAX_N]; 13 int rmat[MAX_N]; 14 int edge[MAX_N][2];15 16 bool hungary(int now,int cnt) 17 { 18 for(int i=0;i<2;i++) 19 { 20 int temp=edge[now][i]; 21 if(vis[temp]!=cnt) 22 { 23 vis[temp]=cnt; 24 if(mat[temp]==-1 || hungary(mat[temp],cnt)) 25 { 26 mat[temp]=now;27 rmat[now]=temp; 28 return true; 29 } 30 } 31 } 32 return false; 33 } 34 35 int main() 36 { 37 cin>>n; 38 for(int i=0;i<n;i++) 39 { 40 cin>>d[i]; 41 if(d[i]>n/2) 42 { 43 cout<<"No Answer"<<endl; 44 return 0; 45 } 46 int x=(i+d[i])%n; 47 int y=(i-d[i]+n)%n; 48 edge[i][0]=min(x,y); 49 edge[i][1]=max(x,y); 50 } 51 memset(vis,0,sizeof(vis)); 52 memset(mat,-1,sizeof(mat)); 53 for(int i=n-1;i>=0;i--) 54 { 55 if(!hungary(i,i+1)) 56 { 57 cout<<"No Answer"<<endl; 58 return 0; 59 } 60 } 61 for(int i=0;i<n;i++) cout<<rmat[i]<<" "; 62 cout<<endl; 63 }
BZOJ 1562 [NOI2009]變換序列:二分圖匹配