POJ - 3020 Antenna Placement(最小覆盖路径)

---恢复内容开始---

https://vjudge.net/problem/POJ-3020

题意

*--代表城市,o--代表空地

       给城市安装无线网,一个无线网最多可以覆盖两座城市,问覆盖所有城市最少要用多少无线。

分析

第一眼看没什么感觉,但要是想到需要处理的点是城市,那这个问题就是一个最小路径覆盖问题了。因为最多覆盖两个城市,即相邻城市才匹配。最小路径覆盖=总节点数-最大匹配数。建图时是双向的,所以最大匹配数/2。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<algorithm>
const int MAXN= 500;//最大顶点数
const int MAXM = 11000;//最大边数
const int INF=0x3f3f3f3f;
using namespace std;

bool g[MAXN][MAXN],used[MAXN];
int linker[MAXN],index[MAXN][MAXN];
int dir[4][2]={{1,0},{0,1},{-1,0},{0,-1}};
int tot;
char s[MAXN][MAXN];

bool dfs(int u){
    for(int v=0;v<tot;v++){
        if(!used[v]&&g[u][v]){
            used[v]=true;
            if(linker[v]==-1||dfs(linker[v])){
                linker[v]=u;
                return true;
            }
        }
    }
    return false;
}
int hungry(){
    int res=0;
    memset(linker,-1,sizeof(linker));
    for(int i=0;i<tot;i++){
        memset(used,false,sizeof(used));
        if(dfs(i)) res++;
    }
    return res;
}
int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        int n,m;
        memset(index,-1,sizeof(index));
        memset(g,false,sizeof(g));
        scanf("%d%d ",&n,&m);
        tot=0;
        for(int i=0;i<n;i++){
            gets(s[i]);
            for(int j=0;j<m;j++){
                if(s[i][j]=='*'){
                    index[i][j]=tot++;
                }
            }
        }
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                if(index[i][j]!=-1){
                    for(int k=0;k<4;k++){
                        int x=i+dir[k][0];
                        int y=j+dir[k][1];
                        if(x>=0&&x<n&&y>=0&&y<m&&index[x][y]!=-1){
                            g[index[i][j]][index[x][y]]=true;
                        }
                    }
                }
            }
        }
        int res=hungry();
        printf("%d\n",tot-res/2);
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/fht-litost/p/9245456.html
今日推荐