【二分图匹配】hdu2819Swap

http://acm.hdu.edu.cn/showproblem.php?pid=2819
题目描述:对给定的n*n的由0,1组成的矩阵,可以交换任意两行或任意两列。问能否使得矩阵的对角线上均为1。

若该矩阵能使对角线上均为1,标记这些1,将其还原,发现这些1互不影响,即不在同一行和同一列上。
那么我们将行作为x集合,列作为y集合,若i行j列为1,连边。
最后找一次最大匹配即可。

这道题在思维上有难度,不容易想到模型。

#include <iostream>
#include <cstdio>
#include <cstring>
#define MAXN 105
using namespace std;

int n ,a ,cnt ,tmp[1005][2] ,cx[MAXN] ,cy[MAXN] ;
bool flag[MAXN][MAXN] ,vis[MAXN] ;

bool dfs(int u)
{
    for(int v=1;v<=n;++v)
        if(!vis[v]&&flag[u][v])
        {
            vis[v]=1;
            if(!cy[v]||dfs(cy[v]))
            {
                cx[u]=v ,cy[v]=u ;
                return 1;
            }
        }
    return 0;
}

int solve()
{
    memset(cx,0,sizeof cx);
    memset(cy,0,sizeof cy);

    int ans=0;
    for(int i=1;i<=n;++i)
        if(!cx[i])
        {
            memset(vis,0,sizeof vis);
            ans+=dfs(i);
        }
    return ans;
}

int main()
{
    while(~scanf("%d",&n))
    {
        memset(flag,0,sizeof flag);
        for(int i=1;i<=n;++i)
            for(int j=1;j<=n;++j)
            {
                scanf("%d",&a);
                if(a)
                    flag[i][j]=1;
            }
        if(solve()<n)
            puts("-1");
        else
        {
            cnt=0;
            for(int i=1;i<=n;++i)
                for(int j=1;j<=n;++j)
                    if(cy[j]==i)
                    {
                        if(i!=j)
                        {
                            ++cnt;
                            tmp[cnt][0]=i ,tmp[cnt][1]=j ;
                            swap(cy[i],cy[j]);
                        }
                        break;
                    }
            printf("%d\n",cnt);
            for(int i=1;i<=cnt;++i)
                printf("C %d %d\n",tmp[i][0],tmp[i][1]);
        }
    }
    return 0;
}

你可能感兴趣的:(二分图匹配,hdu2819)