E - Swap(二分图匹配)

E - Swap(二分图匹配)

思路:将行和列看作两部分,对行进行二分图匹配,然后对找到的匹配进行判断是否在对角线上,不在则交换列。因为每行至少要有一列是1,所以交换行和列都是等价的。所以只交换行或列都是可以的。

时间复杂度: O ( n 3 ) O(n^3)

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;
}
原创文章 201 获赞 165 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_45750972/article/details/105944185