BZOJ1059-[ZJOI2007]矩阵游戏(二分图的最大匹配)

题目链接:BZOJ1059-ZJOI2007-矩阵游戏

题意:

给一个n×n的矩阵,上面有0和1,然后可以对该矩阵进行行列变换(交换行或者交换列),问最后能否将主对角线全部化为1。

题解:

题目可以转化为是否能找到n个行列均不同的点,然后建二分图,左边为行,右边为列,进行最大匹配,若最后匹配数为n则表示可以找到n个行列均不同的点,即有解。

参考代码:

#include<bits/stdc++.h>
using namespace std;
const int MAXN=409;
const int MAXM=209*209;
int T,n;
int match[MAXN];
bool used[MAXN];
struct EDGE
{
    int v,nxt;
} edge[MAXM*2];
int cnt=0,fir[MAXN];
void addedge(int u,int v)
{
    edge[cnt].v=v;
    edge[cnt].nxt=fir[u];
    fir[u]=cnt++;
}
bool dfs(int u)
{
    for(int i=fir[u]; i!=-1; i=edge[i].nxt)
    {
        int v=edge[i].v;
        if(!used[v])
        {
            used[v]=1;
            if(match[v]==-1||dfs(match[v]))
            {
                match[v]=u;
                return 1;
            }
        }
    }
    return 0;
}
int MaxMatch()
{
    int sum=0;
    for(int i=1; i<=n; i++)
    {
        memset(used,0,sizeof(used));
        if(dfs(i))
            sum++;
    }
    return sum;
}
int main()
{
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        cnt=0;
        memset(fir,-1,sizeof(fir));
        memset(match,-1,sizeof(match));
        for(int i=1; i<=n; i++)
            for(int j=1; j<=n; j++)
            {
                int x;
                scanf("%d",&x);
                if(x)
                    addedge(i,j+n);
            }
        int ans=MaxMatch();
        if(ans==n)
            puts("Yes");
        else
            puts("No");
    }
    return 0;
}

发表留言

人生在世,错别字在所难免,无需纠正。