• poj1422


    题意:给定一个有向无环图,在这个图上的某些点上放伞兵,可以使伞兵可以走到图上所有的点。且每个点只被一个伞兵走一次。问至少放多少伞兵。

    分析:最小路径覆盖。我们可以把问题转化为,在图上的边中选出一些边,使得每个点的入度与出度都不超过1。

    我们开始在图上的每个点都放上伞兵,然后没选出一条边,就意味着有一个伞兵可以被取消掉了。也就是说需要的最少伞兵数=点总数-能选出的最大边数。

    我们只要求最大边数即可。用二分图匹配,把每个点拆成两个点,分别加入二分图的两个点集,原图中一条由a到b的边在二分图中是一条由第一个点集中的第a个点到第二个点集中的第b个点。也就是第一个点集的点与出边有关,第二个与入边有关。匹配时也就保证了每个点的入度与出度都不超过1。求最大匹配即为能选出的最大边数。

    View Code
    #include <iostream>
    #include
    <cstdio>
    #include
    <cstdlib>
    #include
    <cstring>
    usingnamespace std;

    #define maxn 150

    int uN, vN;
    bool g[maxn][maxn];
    int xM[maxn], yM[maxn];
    bool chk[maxn];
    int n, m;

    bool SearchPath(int u)
    {
    int v;
    for (v =0; v < vN; v++)
    if (g[u][v] &&!chk[v])
    {
    chk[v]
    =true;
    if (yM[v] ==-1|| SearchPath(yM[v]))
    {
    yM[v]
    = u;
    xM[u]
    = v;
    returntrue;
    }
    }
    returnfalse;
    }

    int MaxMatch()
    {
    int u, ret =0;
    memset(xM,
    -1, sizeof(xM));
    memset(yM,
    -1, sizeof(yM));
    for (u =0; u < uN; u++)
    if (xM[u] ==-1)
    {
    memset(chk,
    false, sizeof(chk));
    if (SearchPath(u))
    ret
    ++;
    }
    return ret;
    }

    void input()
    {
    memset(g,
    0, sizeof(g));
    scanf(
    "%d%d", &n, &m);
    uN
    = vN = n;
    for (int i =0; i < m; i++)
    {
    int a, b;
    scanf(
    "%d%d", &a, &b);
    a
    --;
    b
    --;
    g[a][b]
    =true;
    }
    }

    int main()
    {
    // freopen("t.txt", "r", stdin);
    int t;
    scanf(
    "%d", &t);
    while (t--)
    {
    input();
    int ans = n - MaxMatch();
    printf(
    "%d\n", ans);
    }
    return0;
    }
  • 相关阅读:
    元数据的优势
    老婆从今天开始出差
    清单元数据表中的导出类型定义
    Singleton模式
    拖管代码的优势
    元数据
    "软件随想录"阅读笔记
    《敏捷软件开发》学习笔记:敏捷设计原则
    项目管理中的三个"凡是"
    Python基础(1):数据类型
  • 原文地址:https://www.cnblogs.com/rainydays/p/2083578.html
Copyright © 2020-2023  润新知