1. 程式人生 > >POJ-2226 Muddy Fields---二分圖匹配+巧妙構圖

POJ-2226 Muddy Fields---二分圖匹配+巧妙構圖

span tro style void using match sam eof blank

題目鏈接:

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---二分圖匹配+巧妙構圖