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

题目网址:  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 }

 

posted @ 2017-08-04 22:16  ventricle  阅读(151)  评论(0编辑  收藏  举报