UVa 1663 - Purifying Machine(二分匹配)

题面

没有

思路

求一个若干个01串,其中可能带可以当成任意数字。那么我们考虑一下,*可以变成0或者1,那么并且在这个变形中这两个01串的奇偶性一定改变。那么我们可以建图,将所有在集合中的串和与奇偶性不同并且只改变一个位数的串(异或运算)当成是二分图的左右部,跑一遍匈牙利算出最大匹配,然后由于每个点会被重复,那么我们最终的答案就是集合中所有元素个数之和减去最大匹配数的二分之一。另外这个题01串的话,其实也有点提示你的意思,要学会多揣测出题人的意思。

代码实现

#include<cstdio>
#include<map>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<stack>
using namespace std;
const int maxn=2100;
int maze[maxn][maxn];
int lefta[maxn];
int t[maxn];
char s[20];
int n,m;
int set[maxn];

bool dfs (int u) {
    for (int v=0;v<maxn;v++) if (maze[u][v]&&t[v]==0) {
        t[v]=true;
        if (lefta[v]==-1||dfs (lefta[v])) {
            lefta[v]=u;
            return true;
        }
    }
    return false;
}

inline int hungry () {
    int ans=0;
    memset (lefta,-1,sizeof (lefta));
    for (int i=0;i<maxn;i++) {
        memset (t,0,sizeof (t));
        if (dfs (i)) ans++;
    }
    return ans;
}

int main () {
   while (cin>>n>>m) {
       if (n==0&&m==0) break;
       memset (maze,0,sizeof (maze));
       memset (set,0,sizeof (set));

       for (int i=1;i<=m;i++) {
           cin>>s;
           int temp=0;
           int flag=-1;
           for (int j=0;j<n;j++) {
               if (s[j]==‘1‘) temp|=(1<<j);
               if (s[j]==‘*‘)  flag=j;
           }
           set[temp]=1;
           if (flag!=-1) {
               temp|=1<<flag;
               set[temp]=1;
           }
       }
       int cnt;
       for (int i=0;i<maxn;i++) {
           
           if (set[i]) {
               cnt++;
               int temp;
               for (int j=0;j<n;j++) {
                   temp=i^(1<<j);
                   if (set[temp]) maze[i][temp]=1;
               }
           }
       }
       int ans=hungry ();
       cout<<cnt-hungry ()/2<<endl;
   }
    return 0;
}       

UVa 1663 - Purifying Machine(二分匹配)

上一篇:P4155 [SCOI2015]国旗计划


下一篇:abc 选做