怎么也没想到是二分图。。。
我们首先考虑,交换行或列并不会改变当前行或列黑格的数目,这也就说明了,在同一条直线上的黑格永远不会不在同一条直线。而我们要一条对角线,就相当于找一组黑格,满足没有任何格子在同一条直线上。
怎么建图?既然与一条直线上黑格数目没有关系,我们可以把边看做点,把黑格看作边,在行与列之间连线,容易看出是一个二分图,我们只要看有没有完美匹配就行了
PS:我拿网络流写的,二分图也一样,别忘了初始化邻接表,容易t,我就这样了。。不过还好看到了
AC Code
#include<cstdio>
#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
int tt;
int edge=1;
const int inf=1000000000;
int fst[505];
int nxt[500005];
int v[500005];
int k[500005];
int d[505];
int b[505];
int S=501;
int T=502;
queue<int >q;
void mm()
{
memset(fst,0,sizeof(fst));
memset(nxt,0,sizeof(nxt));
memset(v,0,sizeof(v));
memset(k,0,sizeof(k));
memset(d,-1,sizeof(d));
memset(b,0,sizeof(b));
}
void add(int x,int y,int val)
{
edge++;
nxt[edge]=fst[x];
fst[x]=edge;
v[edge]=y;
k[edge]=val;
}
bool bfs()
{
memset(d,-1,sizeof(d));
d[T]=-1;
d[S]=1;
q.push(S);
while(!q.empty())
{
int x=q.front();
q.pop();
for(int i=fst[x];i;i=nxt[i])
{
if(k[i]&&d[v[i]]==-1)
{
d[v[i]]=d[x]+1;
q.push(v[i]);
}
}
}
return ~d[T];
}
int dfs(int x,int val)
{
if(x==T||!val)
{
return val;
}
int tmp=0;
for(int i=fst[x];i;i=nxt[i])
{
if(k[i]&&d[v[i]]==d[x]+1)
{
int flow=dfs(v[i],min(val,k[i]));
val-=flow;
k[i]-=flow;
k[i^1]+=flow;
tmp+=flow;
if(!val)break;
}
}
if(!tmp)d[x]=-1;
return tmp;
}
int dinic()
{
int tmp=0;
while(bfs())
{
tmp+=dfs(S,inf);
}
return tmp;
}
int n;
int main()
{
scanf("%d",&tt);
int x;
while(tt--)
{
edge=1;
mm();
scanf("%d",&n);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
scanf("%d",&x);
if(x==1)
{
add(i,j+n,inf);
add(j+n,i,0);
}
}
for(int i=1;i<=n;i++)
add(S,i,1),add(i,S,0);
for(int i=1;i<=n;i++)
add(i+n,T,1),add(T,i+n,0);
//printf("%d",dinic());
if(dinic()==n)printf("Yes\n");
else printf("No\n");
}
return 0;
}