Poj--2724(最小边覆盖)
2014-11-05 22:30:47
思路:首先把所有感染的cheeses存到一个数组,注意要去重!!(QAQ坑了两发)然后给每对满足条件:二进制只有一位不同的两个点建边,因为这些点对可以通过一次操作搞定,
为了覆盖所有点,要选一些边,就是最小边覆盖问题了。判断两个数是否只有一位不同:设两数为A、B,且C=A^B,若(C && (C & (C - 1))) == 0那么满足条件,思考。
1 /************************************************************************* 2 > File Name: 2724.cpp 3 > Author: Nature 4 > Mail: 564374850@qq.com 5 > Created Time: Wed 05 Nov 2014 08:57:02 PM CST 6 ************************************************************************/ 7 8 #include <cstdio> 9 #include <cstring> 10 #include <cstdlib> 11 #include <cmath> 12 #include <vector> 13 #include <map> 14 #include <set> 15 #include <stack> 16 #include <queue> 17 #include <iostream> 18 #include <algorithm> 19 using namespace std; 20 #define lp (p << 1) 21 #define rp (p << 1|1) 22 #define getmid(l,r) (l + (r - l) / 2) 23 #define MP(a,b) make_pair(a,b) 24 typedef long long ll; 25 const int INF = 1 << 30; 26 const int maxn = 2010; 27 28 char s[20]; 29 int N,M,cnt; 30 int first[maxn],next[maxn * maxn],ver[maxn * maxn],ecnt; 31 int used[maxn],mat[maxn]; 32 int num[maxn]; 33 34 void Init(){ 35 memset(first,-1,sizeof(first)); 36 ecnt = cnt = 0; 37 } 38 39 void Add_edge(int u,int v){ 40 next[++ecnt] = first[u]; 41 ver[ecnt] = v; 42 first[u] = ecnt; 43 } 44 45 void Build_graph(){ 46 int c; 47 for(int i = 1; i <= cnt; ++i){ 48 for(int j = i + 1; j <= cnt; ++j){ 49 c = num[i] ^ num[j]; 50 if((c && (c & (c - 1))) == 0){ 51 Add_edge(i,j); 52 Add_edge(j,i); 53 } 54 } 55 } 56 } 57 58 bool find(int p){ 59 for(int i = first[p]; i != -1; i = next[i]){ 60 int v = ver[i]; 61 if(used[v] == 0){ 62 used[v] = 1; 63 if(mat[v] == 0 || find(mat[v])){ 64 mat[v] = p; 65 return true; 66 } 67 } 68 } 69 return false; 70 } 71 72 int Hungary(){ 73 int ans = 0; 74 memset(mat,0,sizeof(mat)); 75 for(int i = 1; i <= cnt; ++i){ 76 memset(used,0,sizeof(used)); 77 if(find(i)) ++ans; 78 } 79 return ans; 80 } 81 82 int main(){ 83 while(scanf("%d%d",&N,&M) != EOF){ 84 if(N == 0 && M == 0) 85 break; 86 Init(); 87 while(M--){ 88 scanf("%s",s); 89 int val1 = 0,val2 = 0,fac = 1,flag = 0; 90 for(int i = N - 1; i >= 0; --i){ 91 if(s[i] == '*'){ 92 val2 = val1; 93 val1 += fac; 94 flag = 1; 95 } 96 else if(s[i] == '1'){ 97 val1 += fac; 98 if(flag) val2 += fac; 99 } 100 fac <<= 1; 101 } 102 num[++cnt] = val1; 103 if(flag) num[++cnt] = val2; 104 } 105 sort(num + 1,num + cnt + 1); 106 cnt = unique(num + 1,num + cnt + 1) - num - 1; 107 Build_graph(); 108 printf("%d\n",cnt - Hungary() / 2); 109 } 110 return 0; 111 }