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

时间:2023-03-09 16:29:59
poj 3020 Antenna Placement (最小路径覆盖)

链接:poj 3020

题意:一个矩形中,有n个城市‘*’。‘o’表示空地,如今这n个城市都要覆盖无线,若放置一个基站,

那么它至多能够覆盖本身和相邻的一个城市,求至少放置多少个基站才干使得全部的城市都覆盖无线?

思路:求二分图的最小路径覆盖(无向图)

最小路径覆盖=点数-最大匹配数

注:由于为无向图,每一个顶点被算了两次,最大匹配为原本的两倍。

因此此时最小路径覆盖=点数-最大匹配数/2

#include<stdio.h>
#include<string.h>
int edge[450][450],num,used[510],link[510];
int x[4]={-1,1,0,0},y[4]={0,0,-1,1};
int dfs(int pos)
{
int i;
for(i=0;i<num;i++)
if(edge[pos][i]&&!used[i]){
used[i]=1;
if(link[i]==-1||dfs(link[i])){
link[i]=pos;
return 1;
}
}
return 0;
}
int main()
{
char s[45][15];
int n,m,i,j,k,sum,T,c,r,a[45][15];
scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&m);
num=0;
for(i=0;i<n;i++){
scanf("%s",s[i]);
for(j=0;j<m;j++)
if(s[i][j]=='*')
a[i][j]=num++; //将城市编号,并计算其总数
}
memset(edge,0,sizeof(edge));
for(i=0;i<n;i++)
for(j=0;j<m;j++)
if(s[i][j]=='*'){
for(k=0;k<4;k++){
r=i+x[k];
c=j+y[k];
if(r>=0&&r<n&&c>=0&&c<m&&s[r][c]=='*')
edge[a[i][j]][a[r][c]]=1; //将有关系的城市建边
}
}
sum=0;
memset(link,-1,sizeof(link));
for(i=0;i<num;i++){
memset(used,0,sizeof(used));
sum+=dfs(i);
}
sum=num-sum/2;
printf("%d\n",sum);
}
return 0;
}