hdu 2819 记录路径的二分匹配
题目大意就是给出一个矩阵,每个格子里面要么是0, 要么是1;是否能够经过交换(交换行或者列)使得主对角线上都是1。
其实就行和列的匹配,左边是行,右边是列,然后如果行列交点是1,那么就可以匹配,看是否为完美匹配,然后输出怎么交换的。开始很蒙的,后来仔细去 想,可以这样理解,想要对角线上都是1,那么我们就可以锁定行,来选择列和它匹配,将选择的列移动到和该行形成对角线上是1的位置,比如和第一行匹配的 列,就要移动要第一列,第二行的,就到第二列。其实就是对第i行,找一个第i个数是1的列和它匹配,然后看是否是最大匹配!
路径的输出其实就是 调整匹配使之都为横线,调整的过程就是要输出的路径,调整列和行是相同的,所以锁定一个方向就行了
Sample Input
2
0 1
1 0
2
1 0
1 0
Sample Output
1 R 1 2 -1
2015-05-14:
1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 #include<queue> 7 #include<map> 8 using namespace std; 9 #define MOD 1000000007 10 const int INF=0x3f3f3f3f; 11 const double eps=1e-5; 12 typedef long long ll; 13 #define cl(a) memset(a,0,sizeof(a)) 14 #define ts printf("*****\n"); 15 int n,m,tt; 16 const int MAXN = 510; 17 int a[10000],b[10000]; 18 int uN,vN;//u,v的数目,使用前面必须赋值 19 int g[MAXN][MAXN];//邻接矩阵 20 int linker[MAXN]; 21 bool used[MAXN]; 22 bool dfs(int u) 23 { 24 for(int v = 0; v < vN;v++) 25 if(g[u][v] && !used[v]) 26 { 27 used[v] = true; 28 if(linker[v] == -1 || dfs(linker[v])) 29 { 30 linker[v] = u; 31 return true; 32 } 33 } 34 return false; 35 } 36 int hungary() 37 { 38 int res = 0; 39 memset(linker,-1,sizeof(linker)); 40 for(int u = 0;u < uN;u++) 41 { 42 memset(used,false,sizeof(used)); 43 if(dfs(u))res++; 44 } 45 return res; 46 } 47 int main() 48 { 49 int i,j,k; 50 #ifndef ONLINE_JUDGE 51 freopen("1.in","r",stdin); 52 #endif 53 while(scanf("%d",&n)!=EOF) 54 { 55 uN=vN=n; 56 for(i=0;i<n;i++) 57 for(j=0;j<n;j++) scanf("%d",&g[i][j]); 58 int ans=hungary(); 59 if(ans<n) 60 { 61 printf("-1\n"); 62 continue; 63 } 64 int res=0; 65 for(i=0;i<n;i++) 66 { 67 for(j=0;j<n;j++) 68 { 69 if(linker[j]==i) break; 70 } 71 if(i!=j) 72 { 73 a[res]=i,b[res++]=j; 74 int temp=linker[j]; 75 linker[j]=linker[i]; 76 linker[i]=temp; 77 } 78 } 79 printf("%d\n",res); 80 for(i=0;i<res;i++) 81 { 82 printf("C %d %d\n",a[i]+1,b[i]+1); 83 } 84 } 85 }