zoukankan      html  css  js  c++  java
  • 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
    ",c-dd);
        }
    }
  • 相关阅读:
    js堆和栈
    document.write的用处!
    nodejs选择JavaScript作为开发语言,是因为一般的开发语言的标准库都是带有IO模块的,并且通常这个 模块是阻塞性的,所以nodejs选择了没有自带IO模块的Javascript
    addEventListener和attachEvent的区别
    保留两位小数
    文字图片飞舞
    CSS3 2D 转换
    安装phpstudy之后发现80端口被占用
    docker 部署项目的实战操作
    性能实战第一天基础01-设计测试场景以及如何做性能测试
  • 原文地址:https://www.cnblogs.com/fish7/p/4107088.html
Copyright © 2011-2022 走看看