首页 > 代码库 > hlg1492盒子【最小路径覆盖】
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",n - solve(n));60 }61 return 0;62 }
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。