poj 2724 Purifying Machine(二分图最大匹配)

题意:

有2^N块奶酪,编号为00...0到11..1。

有一台机器,有N个开关。每个开关可以置0或置1,或者置*。但是规定N个开关中最多只能有一个开关置*。

一旦打开机器的开关,机器将根据N个开关的状态对状态对应的编号的奶酪进行消毒。

例如:111 -->  对编号111的奶酪进行消毒。    说明:*代表0或1。 例如:1*1  -->  对编号为101和111的奶酪进行消毒。

现在有一些奶酪被污染了。给出这些奶酷的编号。

问最少需要几次对机器进行设定,使得所有的奶酪都被消毒。

思路:

一个带*的状态可以对两块奶酪进行杀毒。如果两块奶酪都没被之前的操作消过毒,那么这个状态是可以减少机器操作数的。所以这个带*的状态一定要操作的。

则我们要尽量地多找带*的状态,每一种状态消毒的两块奶酪都没有被其它带*的操作消过毒。二分图模型若隐若现了。

要消毒的奶酷复制一份,左边一份,右边一份,如果左边集合的某块奶酪编号和右边集合的某块奶酪编号差一位,则它们可以通过一次操作进行消毒。

求二分图的最大匹配M。

答案: 要消毒的奶酪块数 - M/2

*(未解决):有一个东西不知道咋证。就是这个最大匹配为啥一定就是2倍的关系。

可不可能存在:假设(1-2,3    2-1,3    3-1,2)    (1-2,3,4    2-1,3,4    3-1,2,4    4-1,2,3)

1-2  2-3  3-1  这样的情况。(正确应该是1-2  2-1)    或者      1-2  2-3  3-4  4-1  (虽然可以调整为1-2  2-1  3-4  4-3)

代码:

int n,m,c;
char s[15];
bool ex[2005];
int num[2005];
vector<int> graph[2005];
bool bmask[2005];
int cx[2005],cy[2005];

int findPath(int u){
    int L=graph[u].size();
    rep(i,0,L-1){
        int v=graph[u][i];
        if(!bmask[v]){
            bmask[v]=true;
            if(cy[v]==-1||findPath(cy[v])){
                cy[v]=u;
                cx[u]=v;
                return 1;
            }
        }
    }
    return 0;
}
int MaxMatch(){
    int ans=0;
    rep(i,1,c) cx[i]=cy[i]=-1;
    rep(i,1,c) if(cx[i]==-1){
        mem(bmask,false);
        ans+=findPath(i);
    }
    return ans;
}

bool OneDigit(int x,int y){
    int f=0;
    while(x||y){
        f+=((x&1)!=(y&1));
        x>>=1, y>>=1;
    }
    if(f==1)
        return true;
    else
        return false;
}

int main(){
    while(scanf("%d%d",&n,&m)!=EOF,n||m){
        mem(ex,false);
        c=0;
        rep(i,1,2*m) graph[i].clear();

        rep(i,1,m){
            scanf("%s",s);
            int ts1=0,ts2=0;
            rep(j,0,n-1){
                ts1*=2; ts2*=2;
                if(s[j]!=‘*‘) ts1+=(s[j]-‘0‘), ts2+=(s[j]-‘0‘);
                else ts1+=0, ts2+=1;
            }
            if(!ex[ts1]) { num[++c]=ts1; ex[ts1]=true; }
            if(!ex[ts2]) { num[++c]=ts2; ex[ts2]=true; }
        }

        rep(i,1,c) rep(j,1,c){
            if(OneDigit(num[i],num[j])) graph[i].push_back(j);
        }
        int dd=MaxMatch()/2;
        printf("%d\n",c-dd);
    }
}
时间: 2024-11-10 17:41:11

poj 2724 Purifying Machine(二分图最大匹配)的相关文章

POJ - 2724 Purifying Machine 二分图 最大匹配

题目大意:看了别人的题意: 给出m串长度为n的01串,如果某个串中包含'*'号的,那么这个串就可以变成两个串(因为'*'既可以表示0或者1) 比如字符串*01就可以表示成001,或者101 现在的任务是消除所有的串,给出消除串的规则如下: 1一次消灭一个串. 2如果两个串的差别只有一位的话可以同时消灭这两个串. 问至少需要多少次才能消灭这些串 解题思路:先将这些串去重,化成整数,这样就可以得到两个点集了,点集之间的关系就是一个操作能否消除掉两个串,如果可以的话,则这两个串就存在关系了 #incl

POJ 2724 Purifying Machine(最大独立集)

POJ 2724 Purifying Machine 题目链接 题意:这题题意有点没看懂.看了别人的题解, 给出m串长度为n的01串. 有些串中可能包括,这种串能够表示两个串,为1 和为0. 反复的算一种.比方题目中01 100 011 就代表了四个01串 001 101 100 011 如今我们须要消灭掉全部的01串,消灭方式有两种: 1一次消灭一个串. 2假设两个串的区别仅仅有一位的话能够同一时候消灭这两个串. 问最少多少次操作能够消灭全部的01串 思路:把存在的二进制数保存下来,然后去重.

UVa1663 Purifying Machine (二分图最大匹配,最大流)

链接:http://vjudge.net/problem/UVA-1663 分析:先把原来m个模板串取出来扔进set里去重,然后将去重后的匹配串从1~cnt编号.题目说每个模板串最多一个星号“*”,所以说一个匹配串只有唯一的一个跟它只有一个位上的数字不同的另一个匹配串组合成一个模板串,这就成了二分图最大匹配问题了.然后针对每个匹配串找出和它只有一位数字不同的其它匹配串,把其编号存进数组vector<int> e[i]里.然后对cnt个匹配串以e[i][j]为状态转移进行dfs黑白染色,这样就把

poj 2724 Purifying Machine

Purifying Machine Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 5408   Accepted: 1575 Description Mike is the owner of a cheese factory. He has 2N cheeses and each cheese is given a binary number from 00...0 to 11...1. To keep his chee

POJ 1469 COURSES【二分图最大匹配】

分析:二分图最大匹配 代码: 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <vector> 5 using namespace std; 6 7 const int maxn = 305; 8 9 int n; 10 11 vector<int> G[maxn]; 12 int vis[maxn]; 13 int Link[maxn]; 14

POJ训练计划3020_Antenna Placement(二分图/最大匹配)

解题报告 题目传送门 题意: 在h×w的矩阵中,o表示空地,*表示城市,无线设备只能装在城市上,要使城市全都覆盖需要多少设备.每个设备只能覆盖相邻的两个设备. 思路: 感觉是直接的最大匹配,求出两两匹配的最大数,加上没有匹配的城市就是要的答案. 网上看了题解,正解是最小路径覆盖. 最小路径覆盖=|G|-最大匹配数 在一个N*N的有向图中,路径覆盖就是在图中找一些路经,使之覆盖了图中的所有顶点, 且任何一个顶点有且只有一条路径与之关联:(如果把这些路径中的每条路径从它的起始点走到它的终点, 那么恰

POJ - 1422 Air Raid 二分图最大匹配

题目大意:有n个点,m条单向线段.现在问要从几个点出发才能遍历到所有的点 解题思路:二分图最大匹配,只要一条匹配,就表示两个点联通,两个点联通只需要选取其中一个点即可,所以有多少条匹配,就可以减去多少个点 #include<cstdio> #include<cstring> using namespace std; const int N = 130; int g[N][N], vis[N], link[N]; int n, m; void init() { memset(g, 0

POJ 2446 Chessboard(二分图最大匹配)

题意: M*N的棋盘,规定其中有K个格子不能放任何东西.(即不能被覆盖) 每一张牌的形状都是1*2,问这个棋盘能否被牌完全覆盖(K个格子除外) 思路: M.N很小,把每一个可以覆盖的格子都离散成一个个点,然后二分图最大匹配. 一个重要的问题**:可不可能存在建完的图是这样的情况:1-2,2-3,3-4,4-5,5-1?这种情况二分图最大匹配是5,但实际上答案是不对的. 证明:不可能存在这样的由奇个点构成的环图.我们按这种方法来看看能不能构造出这样一个棋盘. 假设有2k+1个个格(奇数),则第k+

[POJ] 2239 Selecting Courses(二分图最大匹配)

题目地址:http://poj.org/problem?id=2239 Li Ming大学选课,每天12节课,每周7天,每种同样的课可能有多节分布在不同天的不同节.问Li Ming最多可以选多少节课.把n种课划分为X集合,把一周的84节课划分为Y集合, 从Xi向Yi连边,那么就转化成了求二分图的最大匹配数,然后匈牙利算法就可以了. 1 #include<cstdio> 2 #include<iostream> 3 #include<string.h> 4 #includ