POJ 1422 - Air Raid(二分图匹配)

来源:互联网 发布:php判断是否微信打开 编辑:程序博客网 时间:2024/05/16 19:08

题目:

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

题意:

n个点m条边,求出最少数量的伞兵,使得这些伞兵能访问所有的路口。

思路:

二分图, 最小路径覆盖. 一个重要定理: 最小路径覆盖数 = 节点数-最大匹配数 = 最大独立集。

 使用拆点法。若有边<u,v,>,则构造一条边<u,v'>,得到一个二分图,其最大匹配相当于原图中的最小路径覆盖的边数,那么原图的最小路径覆盖数 = 节点数-覆盖边数(最大匹配数)。

AC.

#include <iostream>#include <cstdio>#include <cstring>using namespace std;const int maxn = 125;int g[maxn][maxn], linker[maxn];bool used[maxn];int n;bool dfs(int u){    for(int v = 0; v < n; ++v) {        if(g[u][v] && !used[v]) {            used[v] = 1;            if(linker[v] == -1 || dfs(linker[v])) {                linker[v] = u;                return true;            }        }    }    return false;}int hungary(){    int res = 0;    memset(linker, -1, sizeof(linker));    for(int u = 0; u < n; ++u) {        memset(used, 0, sizeof(used));        if(dfs(u)) res++;    }    return res;}int main(){    //freopen("in", "r", stdin);    int T;    scanf("%d", &T);    while(T--) {        int m;        scanf("%d", &n);        scanf("%d", &m);        memset(g, 0, sizeof(g));        for(int i = 0; i < m; ++i) {            int u, v;            scanf("%d %d", &u, &v);            u--; v--;            g[u][v] = 1;        }        int ans = hungary();        printf("%d\n", n - ans);    }    return 0;}


0 0