先按套路,把矩阵按行和列缩点,格子为1的就在所在行列加边
然后二分图求最大匹配,如果是n,代表可行,小于n就输出-1
然后根据匈牙利算法之后所得的linker,输出操作步骤
遍历linker,如果linker[i]!=i,说明需要交换i与linker[i],如果i代表列就是列交换,否则就是行交换
交换后linker[linker[i]]=linker[i],linker[i]=linker[linker[i]],循环直到linker[i]=i
详见代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
using namespace std;
typedef long long ll;
const int N=100+10;
int g[N][N];
int linker[N];
bool used[N];
int n;
bool dfs(int u)
{
for(int i=1;i<=n;i++)
{
if(used[i]||!g[u][i]) continue;
used[i]=true;
if(linker[i]==-1||dfs(linker[i]))
{
linker[i]=u;
return true;
}
}
return false;
}
int hungary()
{
int res=0;
memset(linker,-1,sizeof(linker));
for(int i=1;i<=n;i++)
{
memset(used,false,sizeof(used));
if(dfs(i)) res++;
}
return res;
}
int a[N],b[N];
int main()
{
while(~scanf("%d",&n))
{
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
scanf("%d",&g[i][j]);
int num=hungary();
if(num==n)
{
int m=0;
for(int i=1;i<=n;i++)
{
while(linker[i]!=i)
{
a[m]=i;
b[m]=linker[i];
m++;
int t=linker[i];
linker[i]=linker[linker[i]];
linker[t]=t;
}
}
printf("%d\n",m);
for(int i=0;i<m;i++)
printf("C %d %d\n",a[i],b[i]);
}
else printf("-1\n");
}
return 0;
}