首页 > 代码库 > poj 3020 Antenna Placement (最小路径覆盖)

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;
}


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