Poj--2226(最小点覆盖,块建图)

2014-11-05 14:11:41

思路:这题和ZOJ1654有点像,建图方法类似,但是建图意义不一样。

  这题中的木板长度可以变-。-.....所以一开始不知道怎么下手,其实转念一想把有草的地方看成墙(木板不能跨过去),然后按照块来编号(和zoj1654类似),于是我们有了行块编号和列块编号。然后扫一遍图,如果发现某个格子为‘*'(即泥地)那么给这个格子的行块号和列块号之间建边....扫完后,所有需要用木板覆盖的泥地就转化成了图中的边,然后思考:选了行块a,代表覆盖行块a所有出边,类似地选列块b,代表覆盖列块b所有出边,于是问题转化成了最小点覆盖问题。

  1 /*************************************************************************
  2     > File Name: 2226.cpp
  3     > Author: Nature
  4     > Mail: 564374850@qq.com 
  5     > Created Time: Wed 05 Nov 2014 01:59:46 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 = 60;
 27 const int Maxn = 2510;
 28 
 29 int R,C,cr,cc;
 30 int row[maxn][maxn],col[maxn][maxn];
 31 char g[maxn][maxn];
 32 int first[Maxn],next[Maxn],ver[Maxn],ecnt;
 33 int used[Maxn],mat[Maxn];
 34 
 35 void Init(){
 36     memset(row,0,sizeof(row));
 37     memset(col,0,sizeof(col));
 38     memset(first,-1,sizeof(first));
 39     ecnt = cr = cc = 0;
 40 }
 41 
 42 void Add_edge(int u,int v){
 43     next[++ecnt] = first[u];
 44     ver[ecnt] = v;
 45     first[u] = ecnt;
 46 }
 47 
 48 void Build_graph(){
 49     for(int i = 0; i < R; ++i){
 50         for(int j = 0; j < C; ++j){
 51             int u = row[i][j];
 52             int v = col[i][j];
 53             if(u && v)
 54                 Add_edge(u,v);
 55         }
 56     }
 57 }
 58 
 59 bool find(int p){
 60     for(int i = first[p]; i != -1; i = next[i]){
 61         int v = ver[i];
 62         if(used[v] == 0){
 63             used[v] = 1;
 64             if(mat[v] == 0 || find(mat[v])){
 65                 mat[v] = p;
 66                 return true;
 67             }
 68         }
 69     }
 70     return false;
 71 }
 72 
 73 int Hungary(){
 74     int ans = 0;
 75     memset(mat,0,sizeof(mat));
 76     for(int i = 1; i <= cr; ++i){
 77         memset(used,0,sizeof(used));
 78         if(find(i)) ++ans;
 79     }
 80     return ans;
 81 }
 82 
 83 int main(){
 84     while(scanf("%d%d",&R,&C) != EOF){
 85         Init();
 86         for(int i = 0; i < R; ++i)
 87             scanf("%s",g[i]);
 88         for(int i = 0; i < R; ++i){
 89             int flag = 0;
 90             for(int j = 0; j < C; ++j){
 91                 if(g[i][j] == '*'){
 92                     if(!flag) ++cr;
 93                     row[i][j] = cr;
 94                     flag = 1;
 95                 }
 96                 else if(g[i][j] == '.')
 97                     flag = 0;
 98             }
 99         }
100         for(int j = 0; j < C; ++j){
101             int flag = 0;
102             for(int i = 0; i < R; ++i){
103                 if(g[i][j] == '*'){
104                     if(!flag) ++cc;
105                     col[i][j] = cc;
106                     flag = 1;
107                 }
108                 else if(g[i][j] == '.')
109                     flag = 0;
110             }
111         }
112         Build_graph();
113         printf("%d\n",Hungary());
114     }
115     return 0;
116 }

 

posted @ 2014-11-05 14:23  Naturain  阅读(179)  评论(0编辑  收藏  举报