E - Swap(二分图匹配)
思路:将行和列看作两部分,对行进行二分图匹配,然后对找到的匹配进行判断是否在对角线上,不在则交换列。因为每行至少要有一列是1,所以交换行和列都是等价的。所以只交换行或列都是可以的。
时间复杂度:
AC代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<utility>
using namespace std;
const int N=105;
int g[N][N],vis[N],mh[N],n;
pair<int,int> a[N*10];
int find(int u){
for(int i=1;i<=n;i++)
if(g[u][i]&&!vis[i]){
vis[i]=1;
if(!mh[i]||find(mh[i])){
mh[i]=u;
return 1;
}
}
return 0;
}
int fun(){
int ans=0;memset(mh,0,sizeof mh);
for(int i=1;i<=n;i++){
memset(vis,0,sizeof vis);
ans+=find(i);
}
return ans;
}
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]);
if(fun()<n) puts("-1");
else {
int k=0;
for(int i=1;i<=n;i++){
int p=0;
for(int j=1;j<=n;j++){
if(mh[j]==i){
p=j;
break;
}
}
if(p!=i){ //找到交换的列.
a[++k]={i,p};
swap(mh[i],mh[p]);//对应的匹配也要换
}
}
printf("%d\n",k);
for(int i=1;i<=k;i++)
printf("C %d %d\n",a[i].first,a[i].second);
}
}
return 0;
}