【二分图】【建图】bzoj1059 矩阵游戏
行列作为点 行为左部 列为右部 黑色格点表示从左部向右部连边
使左上角到右下角的连线上的格子均为黑色 一个行只能和一个列连边 相当于匹配
显然每种完美匹配对应了一个方案
并不需要考虑如何调换和调换行列后方阵是什么样的 从而降低时间复杂度
#include<cstdio>
#include<cstring>
using namespace std;
const int N=200+5;
int n,m,match[N]; bool vis[N];
int num,last[N],nxt[N*N],ver[N*N];
inline void add(int x,int y)
{nxt[++num]=last[x]; last[x]=num; ver[num]=y;}
bool dfs(int x)
{for(int i=last[x],y;i;i=nxt[i])
{if(!vis[y=ver[i]])
{vis[y]=1;
if(!match[y] || dfs(match[y]))
{match[y]=x; return 1;}
}
}
return 0;
}
int main()
{
int t,r,cnt; scanf("%d",&t);
while(t--)
{memset(match,0,sizeof(match));
memset(last,0,sizeof(last));
cnt=num=0;
scanf("%d",&n);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{scanf("%d",&r);
if(r) add(i,j);
}
for(int i=1;i<=n;i++)
{memset(vis,0,sizeof(vis));
if(dfs(i)) cnt++;
else break;
}
if(cnt==n) printf("Yes\n");
else printf("No\n");
}
return 0;
}