码迷,mamicode.com
首页 > 其他好文 > 详细

[ZJOI2007]矩阵游戏

时间:2019-02-03 20:57:27      阅读:176      评论:0      收藏:0      [点我收藏+]

标签:sizeof   变换   一个   坐标   color   gis   memset   ret   style   

这道题是一个不错的题,难点就在于建模。

交换操作过程中,同一行的黑块是不会被拆开,同理纵块也是。

接着目标状态就是一条对角线上全都是黑块。

我们倒过来想,看看能否从目标状态变成初始状态。

对于所有的黑块$(x,y)$(左边行右边列,点分行列),我们连条边$x \leftarrow \rightarrow y$。

显然目标状态应该是完全匹配的。

交换两行$i$、$j$,所有在行$i$、$j$的黑块的横坐标交换,纵坐标不变就是将所有指向行$i$的点的指向改成行$j$,所有指向行$j$的点改指向行$i$。

同理纵坐标也是。

等效替代下发现实质上与交换点$i$和点$j$的效果一样。

也就是从目标状态无论怎样变换匹配数不变且满。

且以上操作可逆。

所以我们检查下原图是否能全部匹配即可。

 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 const int maxn = 200 + 5;
 6 
 7 int vis[maxn], lk[maxn], e[maxn][maxn];
 8 int n, T;
 9 
10 bool find(int u, int tag) {
11     for (register int v = 1; v <= n; ++v)
12         if (e[u][v] && vis[v] != tag) {
13             vis[v] = tag;
14             if (!lk[v] || find(lk[v], tag)) {
15                 lk[v] = u;
16                 return true;
17             }
18         }
19     return false;
20 }
21 
22 int main() {
23     scanf("%d", &T);
24     for (register int kase = 1; kase <= T; ++kase) {
25         scanf("%d", &n);
26         for (register int i = 1; i <= n; ++i)
27             for (register int j = 1; j <= n; ++j) {
28                 int x;
29                 scanf("%d", &x);
30                 e[i][j] = x;
31             }
32         memset(vis, 0, sizeof(vis));
33         memset(lk, 0, sizeof(lk));
34         register int cnt = 0;
35         for (register int i = 1; i <= n; i++)
36             if (find(i, i)) cnt++;
37         if (cnt == n) printf("Yes\n");
38         else printf("No\n");
39     }
40     return 0;
41 }

 

[ZJOI2007]矩阵游戏

标签:sizeof   变换   一个   坐标   color   gis   memset   ret   style   

原文地址:https://www.cnblogs.com/ac-evil/p/10350953.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!