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 }

 

posted @ 2014-11-05 20:56  Naturain  阅读(113)  评论(0编辑  收藏  举报