您的位置:首页 > 其它

[ZJOI2007]矩阵游戏

2018-09-03 17:58 169 查看

嘟嘟嘟

 

这道题如果不看题解,我是绝对想不到二分图匹配的。

咱们先不想二分图匹配的事,先想想什么状态是有解的:只要每一行都有一个黑块,且每一个黑块都在不同的一列,那么一定有解。因为即使这些黑块不在主对角线上,我们也可以通过交换行(列)来达到这个最终状态,这就像不断交换两个数来给一个序列排序一样。

然后考虑建图,每一行作为一个节点,为二分图的左部;每一列也作为一个节点,作为图的右部。如果(i, j)为黑,就给(i, j)连一条边。因为交换任意两行(列)是不会改变图的,可以这么想:每一行的编号不是绝对的,而是最最开始的编号,那么如果把1和3行交换,图上就是把节点1以及他所连的边挪到了3的位置上,3又挪到了1的位置上。

最后只要判断匹配数是否等于n即可。

1 #include<cstdio>
2 #include<iostream>
3 #include<cmath>
4 #include<algorithm>
5 #include<cstring>
6 #include<cstdlib>
7 #include<cctype>
8 #include<vector>
9 #include<stack>
10 #include<queue>
11 using namespace std;
12 #define enter puts("")
13 #define space putchar(' ')
14 #define Mem(a) memset(a, 0, sizeof(a))
15 typedef long long ll;
16 typedef double db;
17 const int INF = 0x3f3f3f3f;
18 const db eps = 1e-8;
19 const int maxn = 405;
20 inline ll read()
21 {
22     ll ans = 0;
23     char ch = getchar(), last = ' ';
24     while(!isdigit(ch)) {last = ch; ch = getchar();}
25     while(isdigit(ch)) {ans = ans * 10 + ch - '0'; ch = getchar();}
26     if(last == '-') ans = -ans;
27     return ans;
28 }
29 inline void write(ll x)
30 {
31     if(x < 0) x = -x, putchar('-');
32     if(x >= 10) write(x / 10);
33     putchar(x % 10 + '0');
34 }
35
36 int t;
37
38 struct Edge
39 {
40     int from, to, cap, flow;
41 };
42 vector<Edge> edges;
43 vector<int> G[maxn];
44 void addEdge(int from, int to)
45 {
46     edges.push_back((Edge){from, to, 1, 0});
47     edges.push_back((Edge){to, from, 0, 0});
48     int sz = edges.size();
49     G[from].push_back(sz - 2);
50     G[to].push_back(sz - 1);
51 }
52
53 void init()
54 {
55     edges.clear();
56     for(int i = 0; i < maxn; ++i) G[i].clear();
57 }
58
59 int dis[maxn];
60 bool bfs()
61 {
62     Mem(dis); dis[0] = 1;
63     queue<int> q; q.push(0);
64     while(!q.empty())
65     {
66         int now = q.front(); q.pop();
67         for(int i = 0; i < (int)G[now].size(); ++i)
68         {
69             Edge& e = edges[G[now][i]];
70             if(!dis[e.to] && e.cap > e.flow)
71             {
72                 dis[e.to] = dis[now] + 1;
73                 q.push(e.to);
74             }
75         }
76     }
77     return dis[t];
78 }
79 int cur[maxn];
80 int dfs(int now, int res)
81 {
82     if(now == t || res == 0) return res;
83     int flow = 0, f;
84     for(int& i = cur[now]; i < (int)G[now].size(); ++i)
85     {
86         Edge& e = edges[G[now][i]];
87         if(dis[e.to] == dis[now] + 1 && (f = dfs(e.to, min(res, e.cap - e.flow))) > 0)
88         {
89             e.flow += f;
90             edges[G[now][i] ^ 1].flow -= f;
91             flow += f;
92             res -= f;
93             if(res == 0) break;
94         }
95     }
96     return flow;
97 }
98
99 int maxflow()
100 {
101     int flow = 0;
102     while(bfs())
103     {
104         Mem(cur);
105         flow += dfs(0, INF);
106     }
107     return flow;
108 }
109
110 int main()
111 {
112     int T = read();
113     while(T--)
114     {
115         init();
116         int n = read(); t = n + n + 1;
117         for(int i = 1; i <= n; ++i)
118         {
119             addEdge(0, i); addEdge(i + n, t);
120             for(int j = 1; j <= n; ++j) if(read()) addEdge(i, j + n);
121         }
122         printf("%s\n", maxflow() == n ? "Yes" : "No");
123     }
124     return 0;
125 }
View Code

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: