Error Correction【二分图匹配】

来源

http://codeforces.com/group/TBxCTUW7hQ/contest/297677
Problem I

题意

n个等长且字符集合相同字符串,差别为2的字符串间连边,求最大独立集。

思路

首先利用性质,最大独立集=n-最大匹配。
因为数据不大,场上一直想着跑一般图匹配,忽略了一个性质:一个字符串通过奇数次交换和偶数次交换的两个集合是互相独立的。
所以可以划分成二分图(染色后重新建图),直接跑匈牙利就好了。

代码

#include<bits/stdc++.h>
using namespace std;
#define sz(x) (int)(x).size()

string s[600]; 
int g[600][600];

int mat[600],used[600];
int n;
int hgdfs(int i){
	for (int j=1; j<=n; j++)
		if (g[i][j] && !used[j]) {
			used[j]=1;
			if (mat[j]==-1 || hgdfs(mat[j])){
				mat[j]=i;
				return 1;
			}
		}
	return 0;
}
int hungary(){
	int res=0;
	memset(mat,-1,sizeof(mat));
	for (int i=1; i<=n; i++) {
		memset(used,0,sizeof(used));
		res+=hgdfs(i);
	}
	return res;
}

int g0[600][600],vis[600],col[600];
void mark(int x,int c){
	col[x]=c;
	vis[x]=1;
	for (int i=1; i<=n; i++)
		if (g0[x][i] && !vis[i]) mark(i,-c);
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
	cin>>n;
	for (int i=1; i<=n; i++) cin>>s[i];
	//graph0
	for (int i=1; i<=n; i++){
		for (int j=i+1; j<=n; j++){
			int cnt=0;
			for (int k=0; k<sz(s[i]); k++)
				if (s[i][k]!=s[j][k]) cnt++;
			if (cnt==2) g0[i][j]=g0[j][i]=1;
		}
	}	
	//mark
	for (int i=1; i<=n; i++)
		if (!vis[i]) mark(i,1);
	//graph
	for (int i=1; i<=n; i++)
		for (int j=1; j<=n; j++)
			if (col[i]==1 && col[j]==-1) g[i][j]=g0[i][j];
		
	int ans=n-hungary();
	cout<<ans;
    return 0;
}
posted @ 2020-10-07 08:04  Synnn  阅读(192)  评论(0编辑  收藏  举报