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 }