UVA1663 Purifying Machine (匈牙利算法,二分图最大匹配)

模版集合个数减少是因为匹配串集合中没被匹配过的一对串匹配了。所以就是找一个二分图最大匹配。

因为集合X和Y是不好分开的,但是可以直接跑,两个集合都会跑一遍,所以一个匹配会被算两次,返回的时候除以2就行了。

也有另外一种写法不用除以2的。

#include<bits/stdc++.h>
using namespace std;
const int maxn = 10;
const int N = 1<<maxn;


#define debug(x)\
bitset<16> bs(x);\
cout<<bs<<endl;

bool vis[N];
int match[N];
int dfsT[N], dfsTime, n, m, M,tot;

bool dfs(int u)
{
    for(int i = 0; i < n; i++){
        int v = u^(1<<i);
        if(vis[v] && dfsT[v] != dfsTime){
            dfsT[v] = dfsTime;
            if(!~match[v] || dfs(match[v])){
                match[v] = u;
                return true;
            }
        }
    }
    return false;
}


int MaxMatch()
{
    memset(match,-1,sizeof(int)*M);
    memset(dfsT,0,sizeof(int)*M);
    dfsTime = 0;
    int ans = 0;
    for(int i = 0; i < M; i++){
        if(vis[i]){
            dfsTime++;
            if(dfs(i)) ans++;
        }
    }
    return ans>>1;
}


int read()
{
    M = 1<<n;
    memset(vis,0,sizeof(bool)*M);
    for(int i = 0; i < m; i++){
        int fg = -1,t = 0;
        scanf("\n");
        char ch;
        for(int j = 0;j < n; j++){
            ch = getchar();
            if(ch == '*') fg = j;
            if(ch != '0') t |= 1<<j;
        }
        vis[t] = true;
        if(~fg) vis[t^(1<<fg)] = true;
    }
    int ret = 0;
    for(int i = 0; i < M; i++) if(vis[i]) ret++;
    return ret;
}

int main()
{
    //freopen("in.txt","r",stdin);
    while(scanf("%d%d",&n,&m),n){
        printf("%d\n",read()-MaxMatch());
    }
    return 0;
}

 

posted @ 2015-08-29 21:08  陈瑞宇  阅读(570)  评论(1编辑  收藏  举报