Poj 3020 Antenna Placement【最小边覆盖 匈牙利算法】

来源:互联网 发布:ssh命令指定端口 编辑:程序博客网 时间:2024/05/19 03:23

链接:

http://poj.org/problem?id=3020


题解:

将每个城市看成顶点,如果一个城市四周存在另一个城市则与这个城市连一条双向边,所以这个题目就变成了求最小边覆盖

无向图最小边覆盖数 = 顶点数 - 最大匹配数/2


#include<iostream>#include<stdio.h>#include<algorithm>#include<cmath>#include<stdlib.h>#include <string.h>#include<queue>#include<set>#include<map>#include<stack>#include<time.h>using namespace std;#define MAX_N 505#define inf 0x7fffffff#define LL long long#define ull unsigned long longconst LL INF = 9e18;const int mod = 100000000;typedef pair<double, double>P;bool G[MAX_N][MAX_N];int city[MAX_N][MAX_N];int h, w;int total;int linker[MAX_N];bool used[MAX_N];int dx[4] = {0, 0, -1, 1};int dy[4] = {-1, 1, 0, 0};bool dfs(int u){    for(int i=1;i<=total;i++) {        if(G[u][i] && !used[i]) {            used[i] = true;            if(!linker[i] || dfs(linker[i])) {                linker[i] = u;                return true;            }        }    }    return false;}int hungary(){    int res = 0;    memset(linker, 0, sizeof(linker));    for(int i=1;i<=total;i++) {        memset(used, false, sizeof(used));        if(dfs(i))            res++;    }    return res;}int main(){    int T;    cin >> T;    while(T--) {        cin >> h >> w;        memset(G, false, sizeof(G));        memset(city, 0, sizeof(city));        total = 1;        for(int i=1;i<=h;i++) {            getchar();            for(int j=1;j<=w;j++) {                char c = getchar();                if(c == '*')                    city[i][j] = ++total;            }        }        for(int i=1;i<=h;i++) {            for(int j=1;j<=w;j++) {                if(city[i][j]) {                    for(int k=0;k<4;k++) {                        int nx = i + dx[k];                        int ny = j + dy[k];                        if(city[nx][ny])                            G[city[i][j]][city[nx][ny]] = true;                    }                }            }        }        int ans = hungary();        cout << total - 1 - ans/2 << endl;    }}


0 0