POJ 3020 -Antenna Placement-二分图匹配

题意:一个N*M的矩阵里有K个观测点,你必须放置天线覆盖所有观测点。每个雷达只能天线两个观测点,这两点必须相邻。计算最少天线数。

做法:将所有相邻的观测点连起来,建图。跑一遍匈牙利算法就计算出了最大的覆盖数,除以二就是天线数。还要加上落单的观测点,每个都需要一个天线。

  1 /*--------------------------------------------------------------------------------------*/
  2 //        Helica‘s header
  3 //        Second Edition
  4 //        2015.11.7
  5 //
  6 #include <algorithm>
  7 #include <iostream>
  8 #include <cstring>
  9 #include <ctype.h>
 10 #include <cstdlib>
 11 #include <cstdio>
 12 #include <vector>
 13 #include <string>
 14 #include <queue>
 15 #include <stack>
 16 #include <cmath>
 17 #include <set>
 18 #include <map>
 19
 20 //debug function for a N*M array
 21 #define debug_map(N,M,G) printf("\n");for(int i=0;i<(N);i++) 22 {for(int j=0;j<(M);j++){ 23 printf("%d",G[i][j]);}printf("\n");}
 24 //debug function for int,float,double,etc.
 25 #define debug_var(X) cout<<#X"="<<X<<endl;
 26 /*--------------------------------------------------------------------------------------*/
 27 using namespace std;
 28
 29 const int maxn = 100;
 30 int N,M,T;
 31 int G[10*maxn][10*maxn],Map[maxn][maxn];
 32 int dx[4]={1,-1,0,0},dy[4]={0,0,1,-1};
 33 int linker[10*maxn];
 34 bool used[10*maxn];
 35 int uN,vN;
 36
 37 bool dfs(int u)
 38 {
 39     for(int v=1;v<=vN;v++)
 40     {
 41         if(G[u][v] && !used[v])
 42         {
 43             used[v] = true;
 44             if(linker[v] == -1 || dfs(linker[v]))
 45             {
 46                 linker[v] = u;
 47                 return true;
 48             }
 49         }
 50     }
 51     return false;
 52 }
 53
 54 int hungary()
 55 {
 56     memset(linker,-1,sizeof linker);
 57     int res = 0;
 58     for(int u=1;u<=uN;u++)
 59     {
 60         memset(used,false,sizeof used);
 61         if(dfs(u)) res++;
 62     }
 63     return res;
 64 }
 65
 66 int main()
 67 {
 68     scanf("%d",&T);
 69     while(T--)
 70     {
 71         scanf("%d%d",&N,&M);
 72         char c;
 73         uN = 0;
 74         for(int i=0;i<N;i++)
 75         {
 76             getchar();
 77             for(int j=0;j<M;j++)
 78             {
 79                 scanf("%c",&c);
 80                 if(c == ‘*‘) Map[i][j] = ++uN;
 81                 else Map[i][j] = 0;
 82             }
 83         }
 84         memset(G,0,sizeof G);
 85         vN = uN;
 86         for(int i=0;i<N;i++)
 87         {
 88             for(int j=0;j<M;j++) if(Map[i][j])
 89             {
 90                 int u = Map[i][j];
 91                 for(int p=0;p<4;p++)
 92                 {
 93                     int nx = i+dx[p],ny = j+dy[p];
 94                     if(nx >=0 && nx < N && ny >=0 && ny < M)
 95                     {
 96                         if(int v = Map[nx][ny])
 97                            {
 98                             //printf("u:%d v:%d\n",u,v);
 99                             G[u][v] = G[v][u] = 1;
100                         }
101                     }
102                 }
103             }
104         }
105
106         int ans = hungary();
107         //printf("ans:%d uN:%d\n",ans,uN);
108         printf("%d\n",(uN-ans)+ans/2);
109     }
110 }
时间: 2024-10-18 06:43:05

POJ 3020 -Antenna Placement-二分图匹配的相关文章

POJ 3020 Antenna Placement(二分图建图训练 + 最小路径覆盖)

题目链接:http://poj.org/problem?id=3020 Antenna Placement Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 6692   Accepted: 3325 Description The Global Aerial Research Centre has been allotted the task of building the fifth generation of mobi

POJ - 3020 ? Antenna Placement 二分图最大匹配

http://poj.org/problem?id=3020 首先注意到,答案的最大值是'*'的个数,也就是相当于我每用一次那个技能,我只套一个'*',是等价的. 所以,每结合一对**,则可以减少一次使用,所以就是找**的最大匹配数目. 对于每一个*,和它的上下左右连接一条边(如果是*才连) 那么,这个图是一个二分图,怎么找到左边集合S,右边集合T呢? 我的做法是染色一次,就可以. 这题应该不能贪心吧. 3 5 ***** o***o o*o*o 其实也可以不分开S.T 跑一发最大匹配,然后匹配

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

题目网址:  http://poj.org/problem?id=3020 题意: 用椭圆形去覆盖给出所有环(即图上的小圆点),有两种类型的椭圆形,左右朝向和上下朝向的,一个椭圆形最多可以覆盖相邻的两个小圆点.   思路: 将每个小圆点看作是一个顶点,因为一个椭圆只能覆盖两个小圆点,我们就可以把这个图看成一个二分图.将相邻的两个点,一个看作是X集合内顶点,另一个看成是Y集合内顶点.但要注意的是一个顶点可能不止和一个顶点想连(如上图情况),所以我们要把上述情况看作是一个无向图,而不是有向图.无向图

POJ - 3020 Antenna Placement 二分图 最小路径覆盖

题目大意:有n个城市,要在这n个城市上建立无线电站,每个无线电站只能覆盖2个相邻的城市,问至少需要建多少个无线电站 解题思路:英语题目好坑,看了半天.. 这题和POJ - 2446 Chessboard类似 可以将所有城市分成两个点集,那么之间的连线就代表无线电站的覆盖关系了. 因为所有城市都要覆盖到,所以根据关系,求出最小路径覆盖就能覆盖所有城市了 #include<cstdio> #include<algorithm> #include<cstring> #incl

POJ 3020 Antenna Placement(二分图匹配)

POJ 3020 Antenna Placement 题目链接 题意:给定一个地图,'*'的地方要被覆盖上,每次可以用1 x 2的矩形去覆盖,问最少用几个能覆盖 思路:二分图匹配求最大独立集,相邻*之间连边,然后求最大独立集即可 看这数据范围,用轮廓线dp应该也能搞 代码: #include <cstdio> #include <cstring> #include <vector> #include <algorithm> using namespace s

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

题目传送门 1 /* 2 题意:*的点占据后能顺带占据四个方向的一个*,问最少要占据多少个 3 匈牙利算法:按坐标奇偶性把*分为两个集合,那么除了匹配的其中一方是顺带占据外,其他都要占据 4 */ 5 #include <cstdio> 6 #include <algorithm> 7 #include <cstring> 8 #include <vector> 9 using namespace std; 10 11 const int MAXN = 4e

POJ 3020 Antenna Placement ,二分图的最小路径覆盖

题目大意: 一个矩形中,有N个城市'*',现在这n个城市都要覆盖无线,若放置一个基站,那么它至多可以覆盖相邻的两个城市. 问至少放置多少个基站才能使得所有的城市都覆盖无线? 无向二分图的最小路径覆盖 = 顶点数 –  最大二分匹配数/2 路径覆盖就是在图中找一些路径,使之覆盖了图中的所有顶点,且任何一个顶点有且只有一条路径与之关联: #include<cstdio> #include<cstring> #include<vector> #include<algor

poj 3020 Antenna Placement 解题报告

题目链接:http://poj.org/problem?id=3020 题目意思:首先,请忽略那幅有可能误导他人成分的截图(可能我悟性差,反正有一点点误导我了). 给出一幅 h * w 的图,  “ * ” 表示 point of interest,“ o ” 忽略之.你可以对 " * " (假设这个 “* ”的坐标是 (i, j))画圈,每个圈只能把它四周的某一个点括住(或者是上面(i-1, j) or 下面(i+1, j) or 左边(i, j-1)  or 右边(i, j+1))

poj 3020 Antenna Placement(最小路径覆盖 + 构图)

http://poj.org/problem?id=3020 Antenna Placement Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 7565   Accepted: 3758 Description The Global Aerial Research Centre has been allotted the task of building the fifth generation of mobile ph

POJ 3020 Antenna Placement 最大匹配

Antenna Placement Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 6445   Accepted: 3182 Description The Global Aerial Research Centre has been allotted the task of building the fifth generation of mobile phone nets in Sweden. The most st