• hlg1492盒子【最小路径覆盖】


    大意:有n个盒子,告诉你一些嵌套关系,比如a能放到b里  c能放到a里

    问最少使多少盒子露在外面

    分析:这里要求的是最少DAG的数量,也就是传说中的最小路径覆盖问题

    最小路径覆盖:

    公式:最小路径覆盖 = 节点个数 - 最大匹配

    这儿有一篇关于其解释,

    首先给出公式:DAG的最小路径覆盖数=DAG图中的节点数-相应二分图中的最大匹配数.

    那么对应一个DAG,如何构造相应的二分图?对于DAG中的一个顶点p,二分图中有两个顶点p和p',对应DAG中的一条有向边p->q,二分图中有p-q'的一条无向边.二分图中p属于S集合,p'属于T集合.
    下面我们来解释上面公式为什么成立,思路参考baihacker神牛:


    上图中,对应左边的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的最小路径覆盖数.
     
    代码:
     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 using namespace std;
     5 
     6 const int maxn = 505;
     7 
     8 struct Node {
     9     int to;
    10     int next;
    11 }p[maxn * maxn];
    12 int head[maxn * maxn];
    13 int tot;
    14 void AddEdge(int u, int v) {
    15     p[tot].to = v;
    16     p[tot].next = head[u];
    17     head[u] = tot++;
    18 }
    19 
    20 int Link[maxn];
    21 int vis[maxn];
    22 
    23 bool Find(int u) {
    24     for(int i = head[u]; i; i = p[i].next) {
    25         int v = p[i].to;
    26         if(!vis[v]) {
    27             vis[v] = 1;
    28             if(Link[v] == -1 || Find(Link[v])) {
    29                 Link[v] = u;
    30                 return true;
    31             }
    32         }
    33     }
    34     return false;
    35 }
    36 
    37 int solve(int n) {
    38     int cnt = 0;
    39     memset(Link, -1, sizeof(Link));
    40     for(int i = 1; i <= n; i++) {
    41         memset(vis, 0, sizeof(vis));
    42         if(Find(i)) {
    43             cnt++;
    44         }
    45     }
    46     return cnt;
    47 }
    48 
    49 int main() {
    50     int n, m;
    51     int u, v;
    52     while(EOF != scanf("%d %d",&n, &m)) {
    53         memset(head, 0, sizeof(head));
    54         tot = 1;
    55         for(int i = 0; i < m; i++) {
    56             scanf("%d %d",&u, &v);
    57             AddEdge(u, v);
    58         }
    59         printf("%d
    ",n - solve(n));
    60     }
    61     return 0;
    62 }
    View Code
  • 相关阅读:
    spring 学习-bean创建bean
    [转]spring 学习-bean创建-循环依赖-3
    [转]spring 学习-bean创建-循环依赖-2
    [转]spring 学习-bean创建-循环依赖-1
    2、python2.7,python3.9 ;在不同版本上获得整数类型运行的结果
    记一次Linux bash 命令行卡顿排查之警惕LD_PRELOAD环境变量
    CPU中断数查看与网卡中断绑核
    中华人民共和国 个人信息保护法 (全文学习)八章 七十四条 2021年11月1日起施行
    【模拟试题】旅行
    Vagrant出现的问题整理
  • 原文地址:https://www.cnblogs.com/zhanzhao/p/3903207.html
Copyright © 2020-2023  润新知