这题是个难题,X代表行,Y代表列,i-j连边代表第i行的第i列与第j列连边可以使g[I][I]变成1,那么只需要求最大匹配即可。
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int maxn=100+5;
bool line[maxn][maxn],used[maxn],vis[maxn][maxn];
int gril[maxn],c1[maxn],c2[maxn];
int n;
bool find(int x)
{
for(int j=1;j<=n;j++)
{
if(line[x][j]==true&&used[j]==false)
{
used[j]=true;
if(gril[j]==-1||find(gril[j]))
{
gril[j]=x;
return true;
}
}
}
return false;
}
int main()
{
while(~scanf("%d",&n))
{
memset(line,false,sizeof(line));
memset(gril,-1,sizeof(gril));
memset(vis,false,sizeof(vis));
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
int x;scanf("%d",&x);
if(x) line[i][j]=true;
}
}
int ans=0;
for(int i=1;i<=n;i++){
memset(used,false,sizeof(used));
if(find(i)) ans+=1;
}
if(ans<n) {printf("-1\n");continue;}
else{
int res=0;
for(int i=1;i<=n;i++)
{
int j;
for(j=1;j<=n&&gril[j]!=i;j++);
if(i!=j){
c1[res]=i;c2[res]=j;res++;
int t=gril[i];gril[i]=gril[j];gril[j]=t;
//假如第三列与第六列互换,原本第三列是要给第五列的,但是现在第三列变成了第六列,
//所以所以第六列给第五列,代码底下给一个例子,画一下就马上知道了
}
}
printf("%d\n",res);
for(int i=0;i<res;i++) printf("C %d %d\n",c1[i],c2[i]);
}
}
return 0;
}
6
1 0 0 0 0 0
0 1 0 0 0 0
0 0 0 0 0 1
0 0 0 1 0 0
0 0 1 0 0 0
0 0 0 0 1 0