最小路径覆盖问题(网络流,二分图) & 最小路径点覆盖结论证明

最小路径覆盖问题(luogu)

题目描述

给定有向图 G=(V,E) 。设 P 是 G 的一个简单路(顶点不相交)的集合。

如果 V 中每个定点恰好在PP的一条路上,则称 P 是 G 的一个路径覆盖。

P 中路径可以从 V 的任何一个定点开始,长度也是任意的,特别地,可以为 0 。

G 的最小路径覆盖是 G 所含路径条数最少的路径覆盖。设计一个有效算法求一个 GAP (有向无环图) G 的最小路径覆盖。

输入格式

第一行有 2 个正整数 n 和 m 。 n 是给定 GAP(有向无环图) G 的顶点数, m 是 G 的边数。

接下来的 m 行,每行有两个正整数 i 和 j 表示一条有向边 (i,j)。

输出格式

从第 1 行开始,每行输出一条路径。文件的最后一行是最少路径数。

Solution

借此题的多种解法加深对最小路径点覆盖结论的理解

二分图做法

  • 方法一

设最小路径点覆盖的边集为 E

当不考虑图中所有边时 E 中边数为0,最少路径数为 n

每合法地向 E 中加一条有向边,相当于将两条路径合二为一,最少路径数 - 1

那怎样的边合法呢?

当每个点至多为 E 中一条有向边的起点时, E 合法。

这与二分图中的 “ 1 要素”(每个点至多在一条边中)契合

于是我们将编号为 i 的点分成 i (左部)和 i+n (右部)

对于每条原图中的边,连接(i,j+n)

求答案为 n - 二分图最大匹配

  • 方法二

还是建立方法一中的二分图,求最大匹配,匹配边为放入 E 中的边

此时每个原图中的点最多为一条被选择的原图中边的起点,最多为一条被选择的原图中边的终点

二分图右部的匹配点为一条被选择的原图中边的起点,左部的匹配点为一条被选择的原图中边的终点

考虑右部,每个右部的非匹配点为一条路径的终点,路径条数 = 终点数 = 右部非匹配点数

考虑左部,同理可得到答案

#include <cstdio>
#include <cstdlib>
#include <vector>
using namespace std;
const int N=310,M=6000;
int head[N],tot,ver[M],nxt[M],edge[M];
int n,m,a,b,vis[N],cnt,ans,match[N];
bool flag[N];
vector <int> an;
void add(int x,int y)
{
    ver[++tot]=y,nxt[tot]=head[x],head[x]=tot;
}
bool dfs(int x)
{
    for(int i=head[x],y;i;i=nxt[i])
        if(vis[y=ver[i]]!=cnt)
        {
            vis[y]=cnt;
            if(!match[y] || dfs(match[y]))
            {
                match[y]=x,match[x]=y;
                return 1;
            }
        }
    return 0;
}
int main()
{
    scanf("%d%d",&n,&m);
    while(m--)
    {
        scanf("%d%d",&a,&b);
        add(a,b+n);
    }
    for(int i=1;i<=n;i++)
    {
        cnt++;
        if(dfs(i)) ans++;
    }
    for(int i=1;i<=n;i++)
    {
        if(flag[i]) continue;
        int x=i;
        an.clear();
        while(x>0) flag[x]=true,an.push_back(x),x=match[x]-n;
        int size=an.size();
        for(int i=size-1;i>=0;i--)
            printf("%d ",an[i]);
        puts("");
    }
    printf("%d\n",n-ans);
    return 0;
}

网络流做法

思路与二分图相似(似乎只是用网络流求二分图最大匹配???)

将编号为 i 的点拆成 i 和 i+n,代表作为一条边起点和终点的情况

i 与源点连一条容量为 1 的边,i+n 与汇点连一条容量为 1 的边,

代表它只能作为一条选中边的起点/终点一次

对于原图中的边(i,j),连建的图中的(i,j+n)

通过求最大流求出最多的合法的边

原文地址:https://www.cnblogs.com/hsez-cyx/p/12353226.html

时间: 2024-08-06 13:49:26

最小路径覆盖问题(网络流,二分图) & 最小路径点覆盖结论证明的相关文章

[loj #6003]「网络流 24 题」魔术球 二分图最小路径覆盖,网络流

#6003. 「网络流 24 题」魔术球 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:Special Judge 上传者: 匿名 提交提交记录统计讨论测试数据 题目描述 假设有 n nn 根柱子,现要按下述规则在这 n nn 根柱子中依次放入编号为 1,2,3,4,? 1, 2, 3, 4, \cdots1,2,3,4,? 的球. 每次只能在某根柱子的最上面放球. 在同一根柱子中,任何 2 22 个相邻球的编号之和为完全平方数. 试设计一个算法,计算出在

【最小路径覆盖】【二分图】【最大流】【Dinic】bzoj2150 部落战争

裸的最小路径覆盖. 把每个点拆点,变成二分图. 对于可以连边的点对(i,j):i->j'(1); 对于任意一点i,若i点为'.':S->i(1),i'->T(1); 答案为所有'.'的数量-最大流(最大匹配数). 引用证明: 路径覆盖中的每条简单路径除了最后一个顶点之外都有唯一的后继和它对应:因此匹配边数就是非路径结尾的结点数:因此,匹配边数达到最大时,非路径结尾的结点数大道最大,故路径结尾的节点数目最少. #include<cstdio> #include<cstri

P2764 最小路径覆盖问题(网络流24题之一)

题目描述 «问题描述: 给定有向图G=(V,E).设P 是G 的一个简单路(顶点不相交)的集合.如果V 中每个顶点恰好在P 的一条路上,则称P是G 的一个路径覆盖.P 中路径可以从V 的任何一个顶点开始,长度也是任意的,特别地,可以为0.G 的最小路径覆盖是G 的所含路径条数最少的路径覆盖.设计一个有效算法求一个有向无环图G 的最小路径覆盖.提示:设V={1,2,.... ,n},构造网络G1=(V1,E1)如下: 每条边的容量均为1.求网络G1的( 0 x , 0 y )最大流. «编程任务:

POJ1325 Machine Schedule【二分图最小点覆盖】

题目链接: http://poj.org/problem?id=1325 题目大意: 有两台机器A和B,机器A有N种不同的模式,编号为0~N-1.机器B有M种不同的模式,编号为0~M-1. 在一开始的时候,机器A和B都处于0模式.现在需要用两台机器来处理K项任务,任务编号为0~K-1.每 一项任务都可以在A或B的指定状态下完成.例如任务1可以在机器A的2模式下完成,也可以在机器B的4 模式下完成.对于第i想任务用(i,x,y)来表示第i项任务可以在机器A的x模式下或机器B的y模式下完成. 为了完

cogs_396_魔术球问题_(最小路径覆盖+二分图匹配,网络流24题#4)

描述 http://cojs.tk/cogs/problem/problem.php?pid=396 连续从1开始编号的球,按照顺寻一个个放在n个柱子上,\(i\)放在\(j\)上面的必要条件是\(i+j\)是一个完全平方数.问做多能放到几号球. 分析 cogs是简化版,我在网上找了个完整版的测试数据,要求输出方案... 求最大放几号球不方便,我们考虑枚举最大的球号,计算最少需要多少柱子. 我们对于满足\(j<i\)且\(i+j\)是一个完全平方数的\(i,j\),从\(j\)向\(i\)连一条

[网络流专练3][最小路径覆盖问题]

题目描述 «问题描述: 给定有向图G=(V,E).设P 是G 的一个简单路(顶点不相交)的集合.如果V 中每个顶点恰好在P 的一条路上,则称P是G 的一个路径覆盖.P 中路径可以从V 的任何一个顶点开始,长度也是任意的,特别地,可以为0.G 的最小路径覆盖是G 的所含路径条数最少的路径覆盖.设计一个有效算法求一个有向无环图G 的最小路径覆盖.提示:设V={1,2,.... ,n},构造网络G1=(V1,E1)如下: 每条边的容量均为1.求网络G1的( 0 x , 0 y )最大流. «编程任务:

二分图最大匹配,最小路径覆盖,最小点覆盖,最大独立集,最小边覆盖与建图方法

转载请注明出处(别管写的好坏,码字也不容易):http://blog.csdn.net/hitwhacmer1 前言:         有自己写的,有摘的别人的,前面是摘的,也是无心整理,出错是难免的,反正我都不会证明,智人见智,别被我误导了. §1图论点.边集和二分图的相关概念和性质 点覆盖.最小点覆盖 点覆盖集即一个点集,使得所有边至少有一个端点在集合里.或者说是"点" 覆盖了所有"边"..极小点覆盖(minimal vertex covering):本身为点覆

有向无环图的最小路径覆盖 二分图模型解题

有向无环图中,路径覆盖就是在图中找一些路径,使之覆盖了图中的所有顶点,且任何一个顶点有且只有一条路径与之关联(如果把这些路径中的每条路径从它的起始点走到它的终点,那么恰好可以经过图中的每个顶点一次且仅一次). 最小路径覆盖就是找出最小的路径条数,使之成为原图的一个路径覆盖. 公式:最小路径覆盖=(原图)顶点数-对应的二分图的最大匹配数. 我们通过例题来解释如何把DAG转换为二分图模型. HDU1151Air Raid 题目大意:在一个城镇,有n个路口,和m条单向路,而且这些路不会形成环.现在要弄

UVA 1201 - Taxi Cab Scheme(二分图匹配+最小路径覆盖)

UVA 1201 - Taxi Cab Scheme 题目链接 题意:给定一些乘客,每个乘客需要一个出租车,有一个起始时刻,起点,终点,行走路程为曼哈顿距离,每辆出租车必须在乘客一分钟之前到达,问最少需要几辆出租车 思路:如果一辆车载完一个乘客a,能去载乘客b,就连一条有向边,这样做完整个图形成一个DAG,然后要求的最少数量就是最小路径覆盖,利用二分图最大匹配去做,把每个点拆成两点,如果有边就连边,做一次最大匹配,n - 最大匹配数就是答案 代码: #include <cstdio> #inc