HDU2819Swap(二分图最大匹配)
題目鏈接??http://acm.hdu.edu.cn/showproblem.php?pid=2819
??? 題目大意很明確,交換圖的某些行或者是某些列(可以都換),使得這個N*N的圖對角線上全部都是1.
??? 這里有一點需要說明,就是說題目的交換,其實是將原來圖的某一行移到最后圖的某一行,而不是指先交換兩行,得到一個新圖,再交換新圖的兩行。感覺這里比較坑。
??? 這里先說明的一點就是,如果通過交換某些行沒有辦法的到解的話,那么只交換列 或者 既交換行又交換列 那也沒辦法得到解。其實個人感覺這個可以用矩陣的秩來解釋,所有的對角線都是1,所以也就是矩陣的秩就是N,所以秩小于N就無解。另外,根據矩陣的性質,任意交換矩陣的兩行? 或者? 兩列,矩陣的秩不變,也就保證了如果通過?只交換行? 或? 只交換列 無法得到解的話,那么其他交換形式也必然無解。
??? 既然說是用二分圖的最大匹配,那怎么構建二分圖呢,我們構建的二分圖,第一部分X表示的是橫坐標,第二部分Y表示縱坐標,所以范圍都是1~N,然后如果a[i][j]是1,那我們就從X的i向Y的j引一條邊,那么這條邊的含義就可以解釋為可以將Y的第j列(因為Y表示的是列的集合)移到第i列,使得a[i][i]變成1,這樣就相當于是第i行第i列就變成了1,也就是說對角線多了一個1。
??? 因此我們求這個二分圖的最大匹配(目的是為了讓每一列只與X中的某一行匹配),這樣來就形成了N條邊,那我們只需要將所有匹配的邊的右邊(列)? 和? 左邊(行)所在的列? 交換,這樣一來對角線上這一行就成了1.
??? 上面也也正好提示了如果最大匹配是N,那就存在解,否則無解。
1 #include <map> 2 #include <set> 3 #include <stack> 4 #include <queue> 5 #include <cmath> 6 #include <ctime> 7 #include <vector> 8 #include <cstdio> 9 #include <cctype> 10 #include <cstring> 11 #include <cstdlib> 12 #include <iostream> 13 #include <algorithm> 14 using namespace std; 15 #define eps 1e-15 16 #define MAXN 105 17 #define INF 1000000007 18 #define MAX(a,b) (a > b ? a : b) 19 #define MIN(a,b) (a < b ? a : b) 20 #define mem(a) memset(a,0,sizeof(a)) 21 22 bool G[MAXN][MAXN],vis[MAXN]; 23 int Left[MAXN],N,M,T,a[MAXN],b[MAXN]; 24 25 bool DFS(int u) 26 { 27 for(int v=0;v<=N;v++) if(G[u][v] && !vis[v]) 28 { 29 vis[v] = true; 30 if(!Left[v] || DFS(Left[v])) 31 { 32 Left[v] = u; 33 return true; 34 } 35 } 36 return false; 37 } 38 39 int main() 40 { 41 while(~scanf("%d", &N)) 42 { 43 mem(G); mem(Left); 44 int x,ans = 0; 45 for(int i=1;i<=N;i++) for(int j=1;j<=N;j++) 46 { 47 scanf("%d", &x); 48 if(x)G[i][j] = true; 49 } 50 for(int i=1;i<=N;i++)//求最大匹配 51 { 52 mem(vis); 53 if(DFS(i)) ans ++; 54 } 55 if(ans < N){printf("-1\n");continue;}//小于N無解 56 int tot = 0,j; 57 for(int i=1;i<=N;i++) 58 { 59 for(j=1;j<=N && Left[j]!=i ;j++); 60 if(i != j)//交換第i列和第j列 61 { 62 a[tot] = i; b[tot] = j; tot ++;//記錄結果 63 int t = Left[i]; Left[i] = Left[j]; Left[j] = t; 64 } 65 } 66 printf("%d\n",tot); 67 for(int i=0;i<tot;i++) printf("C %d %d\n", a[i],b[i]); 68 } 69 return 0; 70 }
?
轉載于:https://www.cnblogs.com/gj-Acit/p/3265502.html
《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀總結
以上是生活随笔為你收集整理的HDU2819Swap(二分图最大匹配)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: hdu 4679 树状dp
- 下一篇: 在Fedora8上安装MySQL5.0.