POJ 3020 Antenna Placement(二分图 匈牙利算法)
Posted ventricle
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 }
以上是关于POJ 3020 Antenna Placement(二分图 匈牙利算法)的主要内容,如果未能解决你的问题,请参考以下文章
POJ 3020 Antenna Placement 最小边覆盖
POJ 3020 Antenna Placement 最大匹配