Poj--3020(最小边覆盖)
2014-11-05 20:35:13
思路:最小边覆盖 = 最大独立集 = 点总数 - 最大匹配数。
这题和在一个有洞的图里放1*2的骨牌题是一样的,给每个不是‘o'的点编号,然后扫一遍图,如果发现一对相邻点都是’*’,那么进行建边。然后求最小边覆盖即可。
(在我的理解中,最小边覆盖之所以要求最大匹配:每个匹配让边匹配数减1,因为本来有两个点要覆盖,现在匹配了之后只要选任意一点,另一点也被覆盖。也就是说匹配数是多少,边匹配数就能下降多少,所以最小边覆盖=v - 最大匹配,个人见解,如有不妥,欢迎讨论~)
1 /************************************************************************* 2 > File Name: 3020.cpp 3 > Author: Nature 4 > Mail: 564374850@qq.com 5 > Created Time: Wed 05 Nov 2014 08:11:47 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 = 1700; 27 28 char g[50][20]; 29 int T,h,w,id,mp[50][20]; 30 int first[maxn],next[maxn * maxn],ver[maxn * maxn],ecnt; 31 int used[maxn],mat[maxn]; 32 int dir[4][2] = {{-1,0},{1,0},{0,-1},{0,1}}; 33 34 void Init(){ 35 memset(mp,0,sizeof(mp)); 36 memset(first,-1,sizeof(first)); 37 ecnt = id = 0; 38 } 39 40 void Add_edge(int u,int v){ 41 next[++ecnt] = first[u]; 42 ver[ecnt] = v; 43 first[u] = ecnt; 44 } 45 46 void Build_graph(){ 47 for(int i = 0; i < h; ++i){ 48 for(int j = 0; j < w; ++j) if(mp[i][j]){ 49 for(int k = 0; k < 4; ++k){ 50 int ti = i + dir[k][0]; 51 int tj = j + dir[k][1]; 52 if(ti >= 0 && ti < h && tj >= 0 && tj < w && mp[ti][tj]){ 53 Add_edge(mp[i][j],mp[ti][tj]); 54 } 55 } 56 } 57 } 58 } 59 60 bool find(int p){ 61 for(int i = first[p]; i != -1; i = next[i]){ 62 int v = ver[i]; 63 if(used[v] == 0){ 64 used[v] = 1; 65 if(mat[v] == 0 || find(mat[v])){ 66 mat[v] = p; 67 return true; 68 } 69 } 70 } 71 return false; 72 } 73 74 int Hungary(){ 75 int ans = 0; 76 memset(mat,0,sizeof(mat)); 77 for(int i = 1; i <= id; ++i){ 78 memset(used,0,sizeof(used)); 79 if(find(i)) ++ans; 80 } 81 return ans; 82 } 83 84 int main(){ 85 scanf("%d",&T); 86 while(T--){ 87 Init(); 88 scanf("%d%d",&h,&w); 89 for(int i = 0; i < h; ++i) 90 scanf("%s",g[i]); 91 for(int i = 0; i < h; ++i) 92 for(int j = 0; j < w; ++j) 93 if(g[i][j] == '*') 94 mp[i][j] = ++id; 95 Build_graph(); 96 printf("%d\n",id - Hungary() / 2); 97 } 98 return 0; 99 }