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