poj 2724 Purifying Machine (最小边覆盖)

原创 2015年07月08日 20:07:58

题意具体说什么没怎么看。

大致是说,m个n位的二进制数,有的含有*(一个数最多含1个),含*的可以用0或者1代替,即含*的同时表示两个二进制数。现在可以用任意的n位二进制数去覆盖这m个二进制数,如果存在两个二进制数,只有一位对应位上的数字不同,那么可以用一个二进制数去覆盖这两个。问最少使用多少个二进制数可以覆盖所有的这m个二进制数。


覆盖的过程可以看做匹配的过程。由此想到用图论来解决此题。


建图:

1、对于给出的m个数,如果含有*,则将其拆为两个二进制数。标记并记录出现的不同二进制数,设个数为nn。

2、对于这nn个数,将其拆为2*nn个点,如果某两个数之间恰有1位对应位不同,则该两个数之间连一条边。

3、求一次最大匹配。对于匹配的两个点,可以只用1个二进制数(或者说1条边)去覆盖,其余的各用1个。问题转化为最小边覆盖问题,总数即为nn减去最大匹配数/2(进行了拆点,匹配数增加1倍)


技巧:

关于判断两个十进制数对应的二进制数是否恰有1位对应位上的数字不同。

设两个十进制数为a,b

令c=a^b

如果c=0,说明a与b相等

若c!=0,则c对应的二进制位中的1代表了a、b对应二进制位上的数字不同。

如果仅有1位不同,则c对应的二进制位上,只有1个1。即有c&(c-1)=0

因此,令c=a^b

判断c&&(c&(c-1))是否为1即可。若为1,则恰有1位不同。


#include<iostream>
#include<vector>
#include<cstdio>
#include<cstring>
using namespace std;
#define N (1<<10)
bool T[N],M[N],Map[N][N];
int nn,Left[N],n,m;
char s[15];
int match(int u){
    for(int i=0;i<nn;++i){
        if(Map[u][i]&&!T[i]){
            T[i]=1;
            if(!Left[i]||match(Left[i])){
                Left[i]=u;
                return 1;
            }
        }
    }
    return 0;
}

vector<int> vec;

void toint(){
    int ans=0,a=1;
    for(int i=n-1;i>=0;--i){
        if(s[i]=='1') ans+=a;
        a<<=1;
    }
    if(!M[ans]){
        M[ans]=1;
        vec.push_back(ans);
    }
}

bool judge(int x,int y){
    int c=x^y;
    if(c&&(c&(c-1))==0) return 1;
    return 0;
}
int main()
{
    int i,j;
    while(~scanf("%d%d",&n,&m)&&(n+m)){
        memset(M,0,sizeof(M));
        memset(Map,0,sizeof(Map));
        memset(Left,0,sizeof(Left));
        vec.clear();
        for(i=0;i<m;++i){
            scanf("%s",s);
            for(j=0;j<n;++j) if(s[j]=='*') break;
            if(j<n){
                s[j]='0';
                toint();
                s[j]='1';
                toint();
            }else toint();
        }
        nn=vec.size();
        for(i=0;i<nn;++i)
        for(j=0;j<nn;++j)
            if(judge(vec[i],vec[j])) Map[i][j]=1;
        int ans=0;
        for(i=0;i<nn;++i){
            for(j=0;j<nn;++j) T[j]=0;
            ans+=match(i);
        }
        printf("%d\n",nn-ans/2);
    }
    return 0;
}


版权声明:本文为博主原创文章,未经博主允许不得转载。

poj3020(最小边覆盖)

思路:要安放一下类似雷达之类的东西,相邻的一个点会被覆盖,但是,只能覆盖一个,不管是东西南北,那么另外一个被覆盖的点就不用在安放雷达了,求最少的安放雷达的数目;显然就是最小边覆盖问题; 对每个坐标表定...
  • KIJamesQi
  • KIJamesQi
  • 2015年09月23日 17:02
  • 201

POJ2724 Purifying Machine二分图,最小边覆盖

题目大意是,2^N个奶酪,编号从二进制0000..00到1111..11,现在有台机器有N个开关,每个开关有3种状态,为1,0,*,同时最多只有一个*存在,*可以替代0,1这两种状态,一个清楚操作则是...
  • u011363774
  • u011363774
  • 2014年08月17日 13:06
  • 395

POJ2724 Purifying Machine【二分图最小边覆盖】

题目大意: 有2^N个奶酪,编号从000…00到111…11,现在有台机器有N个开关,每个开关的状态有3个, 分别是'0'、'1'、'*',每个开关只能有一个状态存在。'*'状态可以替代'0'或'1'...
  • u011676797
  • u011676797
  • 2015年04月09日 11:14
  • 537

poj 3020(二分图最小路径覆盖,拆点)

题目链接题目描述: Antenna Placement Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 8534 ...
  • fouzhe
  • fouzhe
  • 2016年07月26日 20:15
  • 423

二分图之最小边覆盖(poj3020)

题目:poj3020 题意:给出一个图,让你用最少的1*2的纸片覆盖掉图中的所有*出现过的地方。基本裸的最小边覆盖。 分析: 最小边覆盖 = 点总数 - 最大匹配 所以就是转化...
  • y990041769
  • y990041769
  • 2014年07月17日 09:39
  • 1249

[bzoj2150] 部落战争(二分图最小边覆盖)

2150: 部落战争 Time Limit: 10 Sec  Memory Limit: 259 MB Submit: 1021  Solved: 572 [Submit][Status][Discu...
  • xljer_
  • xljer_
  • 2017年06月23日 15:34
  • 182

POJ1287-最小生成树

题目:题目链接   题意:给你一个图,然后求最小花费的图使得所有的点都有被连到   分析:最小生成树,需要注意的是这里的边是更新的,每次都需要判断一下是不是边的权值被更新了。Prime竟然不超...
  • u010057864
  • u010057864
  • 2013年10月03日 20:55
  • 588

二分图,最大匹配数,最小点覆盖,最小边覆盖

正式的定义,网上一大把,但他们的作用是让人看不懂…… 二分图:把点分成两个集合X,Y,使得图的边的两个端点总是分别落在X和Y上,不会有X中的点连向X中的点,不会有Y中的点连向Y中的点 匹配:实质上是二...
  • huangshuai147
  • huangshuai147
  • 2016年04月07日 16:59
  • 846

poj1509 最小表示法

1.起始问题 :比较两个字符串是否循环同构        比如说abca和caab是循环同构的(abca和acba不是循环同构) 2.复杂度较高的算法       例举A串的所有循环同构串 和B串...
  • qq_21704477
  • qq_21704477
  • 2016年02月14日 15:05
  • 586

POJ3020 无向图的最小路径覆盖 无向图边覆盖 匈牙利算法巩固训练

很经典的一道题目,做了好几遍,每次都很好地回顾了匈牙利算法。 解决无向图边覆盖问题的步骤如下: 1.拆点; 2.求拆点后图的最小点覆盖,即最大匹配数; 3.使用公式:最小路径覆盖=拆点前点的数量-最大...
  • lwtdzh999
  • lwtdzh999
  • 2016年03月09日 14:50
  • 372
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:poj 2724 Purifying Machine (最小边覆盖)
举报原因:
原因补充:

(最多只允许输入30个字)