【二分图匹配】hdu2819Swap

来源:互联网 发布:seo有哪些优化 编辑:程序博客网 时间:2024/04/30 05:41

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 105using 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;}
0 0
原创粉丝点击