发现了史上最大的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; }