poj 2226 Muddy Fields(二分图最小点覆盖)

B - Muddy Fields
Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u

Description

Rain has pummeled the cows' field, a rectangular grid of R rows and C columns (1 <= R <= 50, 1 <= C <= 50). While good for the grass, the rain makes some patches of bare earth quite muddy. The cows, being meticulous grazers, don't want to get their hooves dirty while they eat. 

To prevent those muddy hooves, Farmer John will place a number of wooden boards over the muddy parts of the cows' field. Each of the boards is 1 unit wide, and can be any length long. Each board must be aligned parallel to one of the sides of the field. 

Farmer John wishes to minimize the number of boards needed to cover the muddy spots, some of which might require more than one board to cover. The boards may not cover any grass and deprive the cows of grazing area but they can overlap each other. 

Compute the minimum number of boards FJ requires to cover all the mud in the field.

Input

* Line 1: Two space-separated integers: R and C 

* Lines 2..R+1: Each line contains a string of C characters, with '*' representing a muddy patch, and '.' representing a grassy patch. No spaces are present.

Output

* Line 1: A single integer representing the number of boards FJ needs.

Sample Input

4 4
*.*.
.***
***.
..*.

Sample Output

4

Hint

OUTPUT DETAILS: 

Boards 1, 2, 3 and 4 are placed as follows: 
1.2. 
.333 
444. 
..2. 
Board 2 overlaps boards 3 and 4.
 
题意:给一张地图,其中有的点有水洼,要用木板把它们覆盖,求最小的木板数量(横着或者纵向)。
思路:

二分图中,选取最少的点数,使这些点和所有的边都有关联(把所有的边的覆盖),叫做最小点覆盖。
把每段连续的横水洼看成集合A中的点,每段连续的纵水洼看成集合B中的点,中间的交点看成连线,
因为每个有水单元必须覆盖,所以所连的2个单元至少有一个被覆盖。
所以求最小点覆盖。思路很巧妙。

而最小点覆盖 = 最大匹配数

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <algorithm>
 4 #include <string>
 5 #include <queue>
 6 #include <cstring>
 7 #include <vector>
 8 using namespace std;
 9 #define maxn 510 
10 int R, C;
11 int h[maxn][maxn], z[maxn][maxn];
12 char mp[55][55];
13 int line[maxn], vis[maxn];
14 int cnth, cntz, ans;
15 vector <int> q[maxn];
16 void init(){
17     memset(h, 0, sizeof(h));
18     memset(z, 0, sizeof(z));
19     memset(q, 0, sizeof(q));
20     cnth = 1;
21     for(int i = 1; i <= R; i++){
22         for(int j = 1; j <= C; j++){
23             if(mp[i][j] == '*') h[i][j] = cnth;
24             if(mp[i][j] == '*' && mp[i][j+1] != '*') cnth++;
25             
26         }
27     }
28     
29     cntz = 1;
30     for(int i = 1; i <= C; i++){
31         for(int j = 1; j <= R; j++){
32             if(mp[j][i] == '*') z[j][i] = cntz;
33             if(mp[j][i] == '*' && mp[j+1][i] != '*') cntz++;
34         }
35     }
36     
37     for(int i = 1; i <= R; i++){
38         for(int j = 1; j <= C; j++){
39             if(mp[i][j] == '*'){
40                 q[h[i][j]].push_back(z[i][j]);
41             }
42         }
43     }
44 }
45 bool find(int x){
46     for(int i = 0; i < q[x].size(); i++){
47         if(!vis[ q[x][i] ] ){
48             vis[ q[x][i] ] = 1;
49             if(!line[q[x][i]] || find(line[q[x][i]])){
50                 line[q[x][i]] = x;
51                 return true;
52             }
53         }
54     }
55     return false;
56 }
57 void hungry(){
58     ans = 0;
59     memset(line, 0, sizeof(line));
60     for(int i = 1; i < 510; i++){
61         memset(vis, 0, sizeof(vis));
62         if(find(i)) ans++;
63     }
64     printf("%d
", ans);
65     
66 }
67 int main(){
68     while(~scanf("%d%d", &R, &C)){
69         memset(mp, '-1', sizeof(mp));
70         for(int i = 1; i <= R; i++){
71             for(int j = 1; j <= C; j++) cin>>mp[i][j];
72         }
73         init();
74         hungry();
75     }
76 
77 
78     return 0;
79 }
原文地址:https://www.cnblogs.com/titicia/p/3905864.html