BZOJ1059矩陣遊戲-二分圖完美匹配
阿新 • • 發佈:2019-01-31
構造一個二分圖,其中行對應的編號是0到n-1,列對應的編號是n到2n-1,若矩陣中的元素m[i][j]為1則,在頂點i和n+j之間連一條邊。求這個圖的最大匹配。如果最大匹配數等於n,說明,矩陣經過一系列操作可以變成這樣的:存在n個1,任意兩個1不在同一行或者同一列。之後通過構造法:對剛才提到的n個1,進行按行操作,若某行中1在第一列,就把該行與第一行交換,此後不再動這行,其餘n-1行按照上述操作依次進行,即可得到題目要求的矩陣:主對角線上的元素均為1.
參考程式碼:
/************************************************************** Problem: 1059 User: sfailsthy Language: C++ Result: Accepted Time:348 ms Memory:1696 kb ****************************************************************/ //BZOJ自動生成這個,很人性化。。。 #include <cstdio> #include <iostream> #include <cstring> #include <vector> using namespace std; const int maxn =400+10; int V; vector<int> G[maxn]; int match[maxn]; bool used[maxn]; void add_edge(int u,int v){ G[u].push_back(v); G[v].push_back(u); } bool dfs(int v){ used[v]=true; for(int i=0;i<G[v].size();i++){ int u=G[v][i],w=match[u]; if(w<0||!used[w]&&dfs(w)){ match[v]=u; match[u]=v; return true; } } return false; } int bitpartite_matching(){ int res=0; memset(match,-1,sizeof(match)); for(int v=0;v<V;v++){ if(match[v]<0){ memset(used,0,sizeof(used)); if(dfs(v)){ res++; } } } return res; } int main(){ int t,n; scanf("%d",&t); while(t--){ scanf("%d",&n); V=2*n; for(int i=0;i<V;i++){ G[i].clear(); } for(int i=0;i<n;i++){ for(int j=0;j<n;j++){ int x; scanf("%d",&x); if(x){ add_edge(i,j+n); } } } int res=bitpartite_matching(); if(res==n){ printf("Yes\n"); } else{ printf("No\n"); } } return 0; }