BZOJ【1059】矩阵游戏

传送门

怎么也没想到是二分图。。。

我们首先考虑,交换行或列并不会改变当前行或列黑格的数目,这也就说明了,在同一横线上的黑格永远不会不在同一横线。而我们要一条对角线,就相当于找一组黑格,满足没有任何格子在同一横线。

怎么建图?既然与一条横线上黑格数目没有关系,我们可以把边看做点,把黑格看作边,在行与列之间连线,容易看出是一个二分图,我们只要看有没有完美匹配就行了

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;
}

猜你喜欢

转载自blog.csdn.net/Richard__Luan/article/details/81025515