1. 程式人生 > >POJ 3020 Antenna Placement(二分圖 匈牙利算法)

POJ 3020 Antenna Placement(二分圖 匈牙利算法)

margin == problem 題目 placement http cstring nbsp amp

題目網址: http://poj.org/problem?id=3020

題意:

用橢圓形去覆蓋給出所有環(即圖上的小圓點),有兩種類型的橢圓形,左右朝向和上下朝向的,一個橢圓形最多可以覆蓋相鄰的兩個小圓點。

技術分享

思路:

將每個小圓點看作是一個頂點,因為一個橢圓只能覆蓋兩個小圓點,我們就可以把這個圖看成一個二分圖。將相鄰的兩個點,一個看作是X集合內頂點,另一個看成是Y集合內頂點。但要註意的是一個頂點可能不止和一個頂點想連(如上圖情況),所以我們要把上述情況看作是一個無向圖,而不是有向圖。無向圖求出的最大匹配數要除以二。

這樣我們就把問題轉換成求最小邊覆蓋:即用最小的邊將所有頂點覆蓋。該值會等於 頂點數-最大匹配數。 至於求二分圖的最大匹配數,直接用匈牙利算法即可。

代碼:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <vector>
 4 using namespace std;
 5 int match[3000];
 6 struct node{
 7     int x,y;
 8 }dir[4]={{1,0},{-1,0},{0,1},{0,-1}};
 9 vector<node>v;
10 int n,m,cnt;
11 char matrix[50][50];
12 int mp[50][50];
13 int book[3000];
14 int e[3000
][3000]; 15 void deal(){ 16 for (int x=0; x<n; x++) { 17 for (int y=0; y<m; y++) { 18 if(matrix[x][y]!=*) continue; 19 int i=mp[x][y]; 20 for (int d=0,xx,yy; d<4; d++) { 21 xx=x+dir[d].x; 22 yy=y+dir[d].y; 23 if
(xx<0 || x>=n || yy<0 || yy>=m || matrix[xx][yy]!=*) continue; 24 int j=mp[xx][yy]; 25 e[i][j]=1; 26 27 } 28 } 29 } 30 } 31 int dfs(int u){ 32 for(int i=1;i<=cnt;i++){ 33 if(!book[i] && e[u][i]){ 34 book[i]=1; 35 if(match[i]==0 || dfs(match[i])){ 36 match[i]=u; 37 return 1; 38 } 39 } 40 } 41 return 0; 42 } 43 int main(){ 44 int t; 45 scanf("%d",&t); 46 while (t--) { 47 int sum=0; 48 cnt=0; 49 v.clear(); 50 memset(match, 0, sizeof(match)); 51 memset(mp, 0, sizeof(mp)); 52 memset(e, 0, sizeof(e)); 53 scanf("%d%d ",&n,&m); 54 for (int i=0; i<n; i++) { 55 gets(matrix[i]); 56 for (int j=0; j<m; j++) { 57 if(matrix[i][j]==*){ 58 mp[i][j]=++cnt; 59 } 60 } 61 } 62 deal(); 63 for (int i=1; i<=cnt; i++) { 64 memset(book, 0, sizeof(book)); 65 if(dfs(i)) sum++; 66 } 67 printf("%d\n",cnt-sum/2); 68 } 69 return 0; 70 }

POJ 3020 Antenna Placement(二分圖 匈牙利算法)