第九篇:P1129
题解补完计划:第九篇
怎么都第九篇了?
显然,在最终状态,是 \((1,1), (2,2) ..., (n,n)\) 我们看成对于行和列连边,那么对于每个都有连边。我们看交换操作,其本质就是将两行或两列的连接状态交换,意思是只要有两个点的连边,那么它就可以交换,所以我们只需要知道初始状态有没有 \(n\) 的匹配就可以了,这个最大流解决就可以了,只需要判断最大流是不是 \(n\) 就可以了。
代码:
#include<bits/stdc++.h>
using namespace std;
#define N 100005
#define intl long long
#define inf (0x7fffffff)
#define For(i,a,b) for(intl i=a;i<=b;i++)
#define deo(i,a,b) for(intl i=a;i>=b;i--)
intl read() {
intl x=0,k=1;char ch=getchar();
while(!isdigit(ch)) {if(ch == '-') k=-1;ch=getchar();}
while(isdigit(ch)) {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
return x*k;
}
struct edge {
intl to, nxt, data;
}e[N<<1];
intl dep[N], h[N], cnt = 1, s, t;
void add(intl from,intl to,intl data) {
e[++cnt]={to,h[from],data};h[from] = cnt;
}
bool bfs() {
For(i,0,t) dep[i] = 0;
dep[s] = 1;
queue<intl> q;q.push(s);
while(q.size()) {
intl u = q.front();q.pop();
for(intl i=h[u];i;i=e[i].nxt) {
intl v = e[i].to;
if(!dep[v] && e[i].data > 0) dep[v] = dep[u] + 1, q.push(v);
}
}
return dep[t];
}
intl dfs(intl u,intl mx) {
if(u == t || !mx) return mx;
intl res = 0;
for(intl i = h[u];i;i=e[i].nxt) {
intl v = e[i].to;
if(dep[v] == dep[u] + 1 && e[i].data > 0) {
intl del = dfs(v, min(mx, e[i].data));
if(!del) dep[v] = 0;
res += del, mx -= del, e[i].data -= del, e[i^1].data += del;
if(!mx) return res;
}
}
return res;
}
intl dinic() {
intl res = 0, x;
while(bfs()) while(x = dfs(s,inf)) res += x;
return res;
}
intl n;
int main() {
intl T = read();
while(T --) {
n = read();
For(i,1,n) For(j,1,n) {
intl x = read();
if(x) add(i,j+n,1), add(j+n,i,0);
}
s = 0, t = n+n+1;
For(i,1,n) add(s,i,1), add(i,s,0), add(i+n,t,1),add(t,i+n,0);
intl ans = dinic();
if(ans == n) puts("Yes");else puts("No");
For(i,0,t) h[i] = 0;cnt = 1;
}
return 0;
}

浙公网安备 33010602011771号