zoukankan      html  css  js  c++  java
  • HDU -1151 二分匹配与DAG图

    题意:

    t组输入。每组数据第一行代表有n个城市,第二行表示有m个街道,而且这些街道都是单向的,它是一个DAG图(有向无环图),每次你派到一个城市一个机器人,它就会沿着道路走下去,你只需要用最少的机器人把所有城市都走一遍就可以了。问你最少多少个机器人

    题解:

    那么很显然像1->2->3->4这样的图,只需要一个机器人就可以了。我们这个时候可以利用拆点就是把{1}拆成两个点{1,1`},也相当于复制了一个1

    本题可以不考虑为啥这一道题目是二分图路径覆盖,我们可以推出来。题目上面说士兵可以从一个城市走到另一个城市,一直到
    不能走。那么可以说像1->2->3这一条路只需要一个士兵,这是因为1与2相连,2与3相连,所以用其他点减去有几条匹配边就是结果了(假设1,2和2,3是两条匹配边)
    可是二分图上的匹配一个点只能用一次,那么我们就可以通过拆点来实现我们的方法

    证明:

    上图中,对应左边的DAG建立构造右边的二分图,可以找到二分图的一个最大匹配M:1-3',3-4',那么M中的这两条匹配边怎样对应DAG中的路径的边?
    使二分图中一条边对应DAG中的一条有向边,1-3'对应DAG图中的有向边1->3,这样DAG中1就会有一个后继顶点(3会是1的唯一后继,因为二分图中一个顶点至多关联一条边!),
    所以1不会成为DAG中一条路径中的结尾顶点,同样,3-4'对应DAG中3->4,3也不会成为结尾顶点,那么原图中总共4个顶点,减去2个有后继的顶点,就剩下没有后继的顶点,即DAG路径的结尾顶点,
    而每个结尾顶点正好对应DAG中的一条路径,二分图中寻找最大匹配M,就是找到了对应DAG中的非路径结尾顶点的最大数目,那么DAG中顶点数-|M|就是DAG中结尾顶点的最小数目,即DAG的最小路径覆盖数.
    本题目求的是“最小覆盖数”,而不是“最小覆盖”
    上一个图的最小覆盖是3,(这里说的是原图)因为他只能找出来一条边,之后用4(总节点)-1(最大匹配)=3

    代码:

     1 #include<stdio.h>
     2 #include<algorithm>
     3 #include<string.h>
     4 #include<iostream>
     5 #include<queue>
     6 #include<vector>
     7 using namespace std;
     8 const int maxn=210;
     9 vector<int>str[maxn];
    10 int n,match[maxn],visit[maxn];
    11 int dfs_solve(int x)
    12 {
    13     int len=str[x].size();
    14     for(int i=0;i<len;++i)
    15     {
    16         int v=str[x][i];
    17         if(!visit[v])
    18         {
    19             visit[v]=1;
    20             if(match[v]==0 || dfs_solve(match[v]))
    21             {
    22                 match[v]=x;
    23                 return 1;
    24             }
    25         }
    26     }
    27     return 0;
    28 }
    29 int main()
    30 {
    31     int t;
    32     scanf("%d",&t);
    33     while(t--)
    34     {
    35         scanf("%d",&n);
    36         int m;
    37         scanf("%d",&m);
    38         while(m--)
    39         {
    40             int u,v;
    41             scanf("%d%d",&u,&v);
    42             str[u].push_back(v);
    43         }
    44         int sum=0;
    45 
    46         memset(match,0,sizeof(match));
    47         for(int i=1;i<=n;++i)
    48         {
    49             memset(visit,0,sizeof(visit));
    50             sum+=dfs_solve(i);
    51         }
    52         //printf("%d
    ",sum);
    53         printf("%d
    ",n-sum);
    54 //        printf("-------------
    ");
    55 //        for(int i=1;i<=n;++i)
    56 //        {
    57 //            printf("%d %d
    ",i,match[i]);
    58 //        }
    59 //        printf("---------------
    ");
    60         for(int i=1;i<=n;++i)
    61             str[i].clear();
    62     }
    63     return 0;
    64 }
    View Code
  • 相关阅读:
    EF CodeFirst EntityTypeConfiguration 自关联映射配置
    DDD 领域驱动设计-看我如何应对业务需求变化,领域模型调整?
    DDD 领域驱动设计-看我如何应对业务需求变化,愚蠢的应对?
    【记录】ASP.NET XSS 脚本注入攻击
    【记录】JS 获取图片原始尺寸-防止图片溢出
    让 ASP.NET vNext 在 Mac OS 中飞呀飞。。。
    Building Modern Web Apps-构建现代的 Web 应用程序(一些感想)
    【记录】ASP.NET MVC RegisterBundles
    【记录】JS 生成 URL 二维码
    关于有默认值的字段在用EF做插入操作时的思考(续)
  • 原文地址:https://www.cnblogs.com/kongbursi-2292702937/p/11493957.html
Copyright © 2011-2022 走看看