BZOJ 1059: [ZJOI2007]矩阵游戏 二分图匹配
怎么说,先引用一下别人的博客吧!(我觉得它很好地反映了我看到这道题后的思路)
的确,如果只判断每一行,每一列是否都至少有一个1,行和每一列都至少有一个1,会WA掉的。后来无奈之下看了题解,是二分图匹配,(然而蒟蒻还不懂,去请教了一下czl,经过教导之后终于懂了)。大致是这样的吧!
如果 X 行 Y 列 有一个 黑格子 ,就在 x 和 y 之间连边(x是指行,y是指列,两者是在二分图的两边的), 然后,我们可以把变换看作交换 X 中的点(不改变它们连边的情况,简单地说,比如交换A和B,如果之前A有一条边连向C,那么交换后A仍有一条边连向C), 使得最后每一个xi 都有一条边连向 y, 这其实就是一个二分图最大匹配的问题。 加油,多学多思考。看了其他人一些有关二分图的题,大多都体现出了一个一一对应的关系,在这里,一一对应的关系可以表现为 如果一开始的两个格子在同一行,那么它们之间就将始终在同一行,那么它们之间就这能有一个去填充这一行的主对角线, 即每一行中只能有一个去填充主对角线。 同理,列也是一样的。
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<vector> 5 #include<queue> 6 #define clr(x,y) memset(x,y,sizeof(x)) 7 #define rep(i,j,k) for(int i = j; i <= k; i++) 8 #define maxn 205 9 using namespace std; 10 11 int read() 12 { 13 int s = 0, t =1; char c = getchar(); 14 while( !isdigit(c) ){ 15 if( c == '-' ) t = -1; c = getchar(); 16 } 17 while( isdigit(c) ){ 18 s = s * 10 + c -'0'; c = getchar(); 19 } 20 return s * t; 21 } 22 23 int mx[maxn], my[maxn], dx[maxn], dy[maxn], n1, n2; 24 vector<int> G[maxn]; 25 queue<int> q; 26 bool vis[maxn]; 27 28 void clear() 29 { 30 while( !q.empty() ) q.pop(); 31 rep(i,0,maxn-1){ 32 G[i].clear(); 33 } 34 } 35 36 bool match(int x) 37 { 38 int s = G[x].size(); 39 rep(i,0,s-1){ 40 int to = G[x][i]; 41 if( !vis[to] && dy[to] == dx[x] + 1 ){ 42 vis[to] = 1; 43 if( !my[to] || match(my[to]) ){ 44 my[to] = x; mx[x] = to; 45 return 1; 46 } 47 } 48 } 49 return 0; 50 } 51 52 int matching(){ 53 clr(mx,0); clr(my,0); 54 int ans = 0; 55 while( true ){ 56 bool flag = 0; 57 while( !q.empty() ) q.pop(); 58 clr(dx,0); clr(dy,0); 59 rep(i,1,n1) if( !mx[i] ) q.push(i); 60 while( !q.empty() ){ 61 int u = q.front(); q.pop(); 62 int s = G[u].size(); 63 rep(i,0,s-1){ 64 int to = G[u][i]; 65 if( !dy[to] ) { 66 dy[to] = dx[u] + 1; 67 if( my[to] ) { 68 dx[my[to]] = dy[to] + 1; 69 q.push(my[to]); 70 } else flag = 1; 71 } 72 } 73 } 74 if( !flag ) break; 75 clr(vis,0); 76 rep(i,1,n1){ 77 if( !mx[i] && match(i) ) ans++; 78 } 79 } 80 return ans; 81 } 82 83 84 int main() 85 { 86 int t = read(); 87 while( t-- ){ 88 clear(); 89 n1 = read(); 90 rep(i,1,n1){ 91 rep(j,1,n1){ 92 if( read() ){ 93 G[i].push_back(j); 94 } 95 } 96 } 97 if( matching() == n1 ) puts("Yes"); 98 else puts("No"); 99 } 100 return 0; 101 }
————————————————