POJ-2226 Muddy Fields---二分图匹配+巧妙构图
Posted 努力努力再努力x
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ-2226 Muddy Fields---二分图匹配+巧妙构图相关的知识,希望对你有一定的参考价值。
题目链接:
https://vjudge.net/problem/POJ-2226
题目大意:
用宽度为1长度不限的木板将水洼‘*’盖住而不盖住草‘.‘
Sample Input
4 4 *.*. .*** ***. ..*.
Sample Output
4
解题思路:
这道题的构图方法十分巧妙,如果有连续的水洼,假设是横排的,那么这几个连续的水洼可以拿一个板子来覆盖,同样,如果竖排也有连续的水洼,那么也可以拿一个板子来覆盖。这样,当一个水洼既可以拿横着的板子,也可以拿竖着的板子覆盖时,就是相交了。那么这个交线就代表了一个水洼,它既可以被横着盖,也可以被竖着盖。现在我们把所有横排的水洼作为1个水洼需要1个木板,竖着的也同理。
有两种覆盖的方法,一种为横着盖一种为竖着盖覆盖后可转化为下图形式
横着盖:(图中数字表示用的是第几块木板)
1.2.
.333
444.
. . 5.
将这些点加入到X序列中
竖着盖:
1.2.
.324
532.
. . 2.
将这些点加入到Y序列中
将图中水洼进行编号一共有九个水洼
1.2.
.345
678.
. . 9.
9号水洼(5, 2)表示九号水洼可由横着的5号木板覆盖也可以由竖着的2号木板覆盖,5号木板和2号木板之间就有一条线
这样就组成一个二分图,最后求最小的顶点覆盖。就是等于保证每个泥地都被横着的木板或者竖着的木板覆盖了。
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<vector> 5 using namespace std; 6 const int maxn = 2500 + 10; 7 8 int cx[maxn], cy[maxn]; 9 bool vis[maxn]; 10 vector<int>G[maxn]; 11 int x, y; 12 //x表示二分图X部的点数 13 //y表示二分图Y部的点数 14 bool dfs(int u) 15 { 16 for(int i = 0; i < G[u].size(); i++) 17 { 18 int v = G[u][i]; 19 if(!vis[v])//如果该点还没进入增广路 20 { 21 vis[v] = 1;//加入增广路 22 if(cy[v] == -1 || dfs(cy[v])) 23 { 24 cx[u] = v; 25 cy[v] = u; 26 return 1; 27 } 28 } 29 } 30 return 0; 31 } 32 33 int maxmatch() 34 { 35 int ans = 0; 36 memset(cx, -1, sizeof(cx)); 37 memset(cy, -1, sizeof(cy)); 38 for(int i = 1; i <= x; i++) 39 { 40 if(cx[i] == -1) 41 { 42 memset(vis, 0, sizeof(vis)); 43 ans += dfs(i); 44 } 45 } 46 return ans; 47 } 48 char Map[55][55]; 49 int cnt[55][55], n, m; 50 void Build()//建图巧妙 51 { 52 int a[55][55], b[55][55]; 53 memset(a, 0, sizeof(a)); 54 memset(b, 0, sizeof(b)); 55 //木板横着放 56 x = 0, y = 0; 57 for(int i = 0; i < n; i++) 58 { 59 for(int j = 0; j < m; j++) 60 { 61 if(Map[i][j] == ‘*‘) 62 { 63 if(Map[i][j - 1] == ‘*‘) 64 a[i][j] = a[i][j - 1]; 65 else a[i][j] = ++x; 66 } 67 } 68 } 69 //木板竖着放 70 for(int j = 0; j < m; j++) 71 { 72 for(int i = 0; i < n; i++) 73 { 74 if(Map[i][j] == ‘*‘) 75 { 76 if(Map[i - 1][j] == ‘*‘) 77 b[i][j] = b[i - 1][j]; 78 else b[i][j] = ++y; 79 //cout<<a[i][j]<<" "<<b[i][j]<<endl; 80 //建边 81 G[a[i][j]].push_back(b[i][j]); 82 } 83 } 84 } 85 } 86 int main() 87 { 88 cin >> n >> m; 89 for(int i = 0; i < n; i++) 90 { 91 cin >> Map[i]; 92 } 93 Build(); 94 cout<<maxmatch()<<endl; 95 return 0; 96 }
以上是关于POJ-2226 Muddy Fields---二分图匹配+巧妙构图的主要内容,如果未能解决你的问题,请参考以下文章
POJ 2226 Muddy Fields(二分匹配 巧妙的建图)
POJ-2226 Muddy Fields---二分图匹配+巧妙构图