题目链接:Swap
*题意:给你一个nn的棋盘,值都是0或1,你可以任意交换两行两列,不要求最少步数,交换的结果让对角线都为1
思路:首先我们可以看出如果可以交换出结果,只依靠行交换或者列交换即可,然后我们要求的是一条对角线,意思是每列匹配的位置必须是固定的行,
我们把行当做二分图的左边,列当做二分图的右边,1的时候就是行和列直接有一条边,
-1问题我们直接用匈牙利算法求出,求出最大匹配是否是n,如果不是的话,说明有些行还没有匹配,所以不符合要求,如果最大匹配是n的话
我们可以去找属于自己的列,如图
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int maxn=1e3+5;
int n,book[maxn],match[maxn],e[maxn][maxn];
int b[maxn],c[maxn];
int dfs(int u)
{
int i;
for(i=1;i<=n;i++)
{
if(book[i]==0&&e[u][i])
{
book[i]=1;
if(match[i]==0||dfs(match[i]))
{
match[i]=u;
return 1;
}
}
}
return 0;
}
int main()
{
while(~scanf("%d",&n))
{
int i,j,k;
memset(e,0,sizeof(e));
memset(b,0,sizeof(b));
memset(book,0,sizeof(book));
memset(c,0,sizeof(c));
memset(match,0,sizeof(match));
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
scanf("%d",&e[i][j]);
int sum=0;
for(i=1;i<=n;i++)
{
memset(book,0,sizeof(book));
if(dfs(i))
sum++;
}
if(sum<n)//看是否满足全部匹配到了
{
printf("-1\n");
continue;
}
k=0;
for(i=1;i<=n;i++)
{
if(match[i]!=i)//灵活利用match数组记录了匹配的行
{
for(j=1;j<=n;j++)//如果当前行匹配出错,找出需要匹配的行在哪里
{
if(match[j]==i)
{
b[k]=i;
c[k]=j;
k++;
swap(match[i],match[j]);
break;
}
}
}
}
printf("%d\n",k);
for(i=0;i<k;i++)
printf("C %d %d\n",b[i],c[i]);
}
}