Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 5649 | Accepted: 2828 |
Description
Input
Output
Sample Input
2Sample Output
17
5
/**************************************************************** * 题目大意:一个矩形中,有N个城市’*’,现在这n * 个城市都要覆盖无线,若放置一个基站,那么它至 * 多可以覆盖相邻的两个城市。 * 问至少放置多少个基站才能使得所有的城市都覆盖无线? * 分析:就是一个最小顶点覆盖的问题; * 解答:可以通过转化为求最大匹配来解决; * 利用公式 最小顶点覆盖=结点数量-最大匹配/2; * * 建图方法:要明确的是,输入的一堆“圈圈星星”可以 * 看做是一张大地图,地图上有所有城市的坐标,但是这里有一个误区: * 不能简单地把城市的两个x、y坐标作为准备构造的二分图的两个顶点集。 * 城市才是要构造的二分图的顶点! * 此处分析转自:http://blog.csdn.net/lyy289065406/article/details/6647040 * 构造方法如下: * 例如输入: * *oo * *** * O*o * 时,可以抽象为一个数字地图: * 100 * 234 * 050 *数字就是根据输入的城市次序作为该城市的编号,0代表该位置没有城市。 *然后根据题目的“范围”规则,从第一个城市开始,以自身作为中心城市,向四个方向的城市进行连线(覆盖) * 因此就能够得到边集:edge(1,2),edge(2,1),edge(3,2),edge(2,3),edge(3,4),edge(4,3),edge(3,5),edge(5,3); * 下来套模板做就OK了; * author: crazy_石头 * 备注:邻接表版本 * Problem: POJ3020--Antenna Placement ***************************************************************************/ #include <iostream> #include <cstdlib> #include <cstdio> #include <cstring> #include <algorithm> #define A system("pause") using namespace std; const int maxn=400+5; char map[maxn][maxn]; int city[maxn][maxn]; int Linker[maxn],head[maxn]; bool used[maxn]; int dx[]={-1,0,1,0}; int dy[]={0,-1,0,1}; int n;//城市数量; int uN,vN;//左右点集; int res;//最大匹配; int cnt,h,w; struct Node { int v,next; }edge[maxn<<2]; bool OK(int x,int y) { if(x<0||x>=h||y<0||y>=w||map[x][y]!='*') return false; return true; } void addedge(int u,int v) { edge[cnt].v=v; edge[cnt].next=head[u]; head[u]=cnt++; } int DFS(int u) { for(int i=head[u];~i;i=edge[i].next) { int v=edge[i].v; if(!used[v]) { used[v]=1; if(Linker[v]==-1||DFS(Linker[v])) { Linker[v]=u; return 1; } } } return 0; } int Hungary() { int res=0; memset(Linker,-1,sizeof(Linker)); for(int i=0;i<uN;i++) { memset(used,0,sizeof(used)); if(DFS(i)) res++; } return res; } int main() { int test; scanf("%d",&test); while(test--) { cnt=0; memset(head,-1,sizeof(head)); n=0; scanf("%d%d%*c",&h,&w); for(int i=0;i<h;i++) scanf("%s",map[i]); //A; for(int i=0;i<h;i++) { for(int j=0;j<w;j++) { if(map[i][j]=='*') { city[i][j]=n++; //printf("%d\n",city[i][j]); //cout<<12345<<endl; //A; } } } //A; for(int i=0;i<h;i++) { for(int j=0;j<w;j++) { if(map[i][j]!='*') continue; for(int k=0;k<4;k++) { int xx=i+dx[k]; int yy=j+dy[k]; if(!OK(xx,yy)) continue; addedge(city[i][j],city[xx][yy]); } } } uN=n; int res=uN-Hungary()/2; printf("%d\n",res); } //A; return 0; } /****************************************** * 这个题目中又出现了两处小错误。 * 1.手误,把+敲成了=。。 * 2.把++n和n++用错了,幸亏改好了1Y * 以后一定要细心啊 ******************************************/