发现了史上最大的BUG ……
Yes打上了YES 调的欲哭无泪&%#*&@!……
不胡扯了 下面是题解
首先我们会发现 同一行用一列上的 黑色格子无论怎样换行 总是在同一行同一列上
那么我们可以把每一行 每一列作为状态 进行二分图匹配
若F[i][j]=1 则表示 第i行 和 第j列 可以匹配 然后直接 匈牙利就行了
形象的说 就是 可以把每一行看做一个士兵 每一列看做一个阵营
每一个士兵都可以到达许多阵营(许多列) 但只能占有一个阵营(一列)
然后就看最多能占有多少阵营就行了 如果等于n 那么有解,否则无解
2333…………(被Shymuel大神嘲讽了好久手速慢,语文没学好各种被骂…………)
蒟蒻就只能描述这些了…………
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<map>
#include<cmath>
using namespace std;
int head[222],d[42222][2],state[222],from[222];
int n,t,cnt,TI;
void insert(int a,int b)
{
d[++cnt][0]=b; d[cnt][1]=head[a]; head[a]=cnt;
}
int hungary(int x)
{
for(int i=head[x]; i; i=d[i][1])
if(state[d[i][0]]!=TI)
{
state[d[i][0]]=TI;//时间戳
if(!from[d[i][0]] || hungary(from[d[i][0]]) )
{
from[d[i][0]]=x;
return 1;
}
}
return 0;
}
int main()
{
scanf("%d",&t);
while( t-- )
{
cnt=0;
memset(head,0,sizeof(head));
memset(from,0,sizeof(from));
scanf("%d",&n);
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
{
int x; scanf("%d",&x);
if(x) insert(i,j);
}
bool flag=0;
for(int i=1; i<=n; i++)
{
TI++;//用一个时间戳可以加速一下匈牙利,拒绝memset
if(!hungary(i)) {flag=1; break; }
}
if(flag) printf("No\n");
else printf("Yes\n");
}
return 0;
}