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;
}