ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

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

2020-02-23 18:52:45  阅读:256  来源: 互联网

标签:二分 原图 一条 覆盖 int 路径 最小 match


最小路径覆盖问题(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;
}
View Code

 

 

 

网络流做法

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

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

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

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

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

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

标签:二分,原图,一条,覆盖,int,路径,最小,match
来源: https://www.cnblogs.com/hsez-cyx/p/12353226.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有