[精]poj2724
Posted 神犇(shenben)
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[精]poj2724相关的知识,希望对你有一定的参考价值。
Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 5027 | Accepted: 1455 |
Description
One day, Mike‘s machine was infected. When Mike found out, he had already done some operations and the cheeses operated by this infected machine were infected too. He cleaned his machine as quickly as he could, and now he needs to clean the infected cheeses with the minimum number of operations. If a cheese is infected, cleaning this cheese with the machine one or more times will make this cheese free from virus again; but if a cheese is not infected, operation on this cheese will make it go bad.
Now given the infected operations Mike has done, you need to find out the minimum number of operations that must be performed to clean all the infected cheeses without making any clean cheese go bad.
Input
Output
Sample Input
3 3 *01 100 011 0 0
Sample Output
2
Source
题意:
题意:迈克有一台可以净化奶酪的机器,用二进制表示净化的奶酪的编号。但是,在某些二进制串中可能包含有‘*‘。例如01*100,‘*‘其实就代表可以取0,1两种情况--> 010100 和011100。现在由于迈克不小心,他以同样的方式弄脏了某些奶酪,问你最少用多少次操作就可以把弄脏的奶酪全净化好。(没有被弄脏过的奶酪不能净化。弄脏过的奶酪可以多次净化。)
思路:
也就是给你一些不同的(判重之后)二进制串,每个串可以通过1次操作净化,也可以把两个只有1位不同的串通过1次操作联合净化.要我们求最少的操作次数.
我们把所有串按其中1的个数和是奇还是偶分成左右两个点集.
对于任意两个串,如果他们只有1位不同,那么就在他们之间连接一条无向边.(这两个串一定分别属于不同的点集)
由于串的总数是固定的,且一个串可以通过单独净化也可以通过联合净化.而我们向让净化的次数最少,我们自然想联合净化(即一次可以净化两个串)的次数尽量多了. 那么我们最多可以进行多少次联合净化呢? 这个数值==我们建立二分图的最大匹配边数.(想想是不是,因为一个串最多只能被净化一次)
假设总的不同串有n个,我们建立二分图的最大匹配数(即联合净化最大次数)为ans,那么我们总共需要n-ans次净化即可.(想想为什么)
当然本题也可以不用把串特意分成左右点集(本程序实现就是用的这种方式:未分左右点集),我们只需要把原图翻倍,然后求翻倍图的最大匹配数ans,最后用n-ans/2即可.
这个题中有很多位运算的有意思的东西
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N=3000+50; int uN,vN; int g[N][N]; int link[N]; int used[N]; int num[N]; int dfs(int u){ for(int v=0;v<vN;v++)//顶点编号从0开始的 if(g[u][v]&&!used[v]){ used[v]=1; if(link[v]==-1||dfs(link[v])){ link[v]=u; return 1; } } return 0; } int hungary(){ int res=0; memset(link,-1,sizeof(link)); for(int u=0;u<uN;u++){ memset(used,0,sizeof(used)); if(dfs(u)) res++; } return res; } int main(){ int n,m; char str[50]; while(scanf("%d%d",&n,&m)==2&&(m+n)){ memset(g,0,sizeof(g)); memset(num,0,sizeof(num)); int cnt=0; while(m--){ cnt++; scanf("%s",&str); int pos=-1; for(int i=0;i<n;i++){ if(str[i]==‘*‘){pos=i;continue;} num[cnt]|=(str[i]-‘0‘)<<i; } if(pos!=-1){ cnt++; num[cnt]=(num[cnt-1]|(1<<pos)); } } sort(num+1,num+cnt+1); num[0]=-1; int i,j; for(j=0,i=1;i<=cnt;i++){ if(num[j]!=num[i]) num[++j] = num[i]; } cnt=j; for(i=1;i<=cnt;i++) for(j=1;j<=cnt;j++){ int c=num[i]^num[j]; if(c&&((c&(c-1))==0))g[num[i]][num[j]]=1; } uN=vN=2050; int ans=cnt-hungary()/2; printf("%d\n",ans); } return 0; }
以上是关于[精]poj2724的主要内容,如果未能解决你的问题,请参考以下文章