zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    Directx
    apr库开发
    linux 上編譯apache
    数字信号处理---FFT
    C# Parallel用法
    C#线程同步--线程通信
    C#线程同步--限量使用
    C#线程安全类型
    C# Task用法
    C# ThreadPool类(线程池)
  • 原文地址:https://www.cnblogs.com/fzulinxin/p/13772164.html
Copyright © 2011-2022 走看看