Luogu 2764 最小路径覆盖问题 / Libre 6002 「网络流 24 题」最小路径覆盖 (网络流,最大流)

Description

给定有向图G=(V,E)。设P是G的一个简单路(顶点不相交)的集合。如果V中每个顶点恰好在P的一条路上,则称P是G的一个路径覆盖。P中路径可以从V的任何一个顶点开始,长度也是任意的,特别地,可以为0。G的最小路径覆盖是G的所含路径条数最少的路径覆盖。

设计一个有效算法求一个有向无环图G的最小路径覆盖。

Input

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

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

Output

第1行开始,每行输出一条(字典序)路径。最后一行是最少路径数。

Sample Input

11 12 1 2 1 3 1 4

2 5

3 6

4 7

5 8

6 9

7 10

8 11

9 11

10 11

Sample Output

1 4 7 10 11

2 5 8

3 6 9

3

Http

Luogu:https://www.luogu.org/problem/show?pid=2764

Libre:https://loj.ac/problem/6002

Source

网络流,最大流

解决思路

这题是sdoi2010星际竞速的弱化版,去掉了费用的限制。

对于每一个点u,我们把它拆成两个点u和u+n,分别作为入点和出点。在源点与所有入点之间连一条容量为1的边,在所有的出点与汇点之间也连一条容量为1的边。再对于每一条有向边u->v,我们连接u的入点和v的出点,容量为1.

这样建图的目的是保证任何一个点只进去一次,出来一次,并且每个点至少都要走一次。

至于如何找出路径呢?

假设我们现在选择第u个点出发,则寻找与其相连的所有边中满足相连的点v为出点且残量为0,因为我们保证了一个点只走一次,所以这个点一定是唯一的。然后再以v为出发点寻找,直到找不到为止。需要注意的是,为了防止重复计算,上面我们经过的所有点都要标记一下,后面就不再经过了。

另:这里使用Dinic实现最大流,关于Dinic算法,请移步我的这篇文章

代码

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std; const int maxN=500;
const int maxM=60000;
const int inf=2147483647; class Edge
{
public:
int v,flow;
}; int n,m;
int cnt=-1;
int Head[maxN];
int Next[maxM];
Edge E[maxM];
int depth[maxN];
int Q[maxM];
int cur[maxN];
bool vis[maxN]; void Add_Edge(int u,int v,int flow);
bool bfs();
int dfs(int u,int flow); int main()
{
memset(Head,-1,sizeof(Head));
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
{
Add_Edge(0,i,1);//连接源点与入点
Add_Edge(i+n,2*n+1,1);//连接出点与汇点
}
for (int i=1;i<=m;i++)
{
int u,v;
scanf("%d%d",&u,&v);
Add_Edge(u,v+n,1);//连接u的入点与v的出点
}
while (bfs())
{
for (int i=0;i<=n*2+1;i++)//当前弧优化
cur[i]=Head[i];
while (int di=dfs(0,inf));
}
memset(vis,0,sizeof(vis));
int Ans=0;
for (int i=1;i<=n;i++)//统计路径
{
if (vis[i]==1)
continue;
int now=i;
bool get;
do
{
cout<<now<<" ";
vis[now]=1;
get=0;
for (int i=Head[now];i!=-1;i=Next[i])
if ((E[i].flow==0)&&(E[i].v>n)&&(E[i].v<=2*n))
{
now=E[i].v-n;
get=1;
break;
}
}
while (get==1);
cout<<endl;
Ans++;
}
cout<<Ans<<endl;//输出路径条数
return 0;
} void Add_Edge(int u,int v,int flow)//加边
{
cnt++;
Next[cnt]=Head[u];
Head[u]=cnt;
E[cnt].v=v;
E[cnt].flow=flow; cnt++;
Next[cnt]=Head[v];
Head[v]=cnt;
E[cnt].v=u;
E[cnt].flow=0;
} bool bfs()//bfs求层次图
{
memset(depth,-1,sizeof(depth));
int t=0,h=1;
Q[1]=0;
depth[0]=1;
do
{
t++;
int u=Q[t];
for (int i=Head[u];i!=-1;i=Next[i])
{
int v=E[i].v;
if ((E[i].flow>0)&&(depth[v]==-1))
{
depth[v]=depth[u]+1;
h++;
Q[h]=v;
}
}
}
while (h!=t);
if (depth[n*2+1]==-1)//当汇点不存在层次图中时,说明增广完毕
return 0;
return 1;
} int dfs(int u,int flow)//dfs增广
{
if (u==n*2+1)
return flow;
for (int &i=cur[u];i!=-1;i=Next[i])
{
int v=E[i].v;
if ((depth[v]==depth[u]+1)&&(E[i].flow>0))
{
int di=dfs(v,min(flow,E[i].flow));
if (di>0)
{
E[i].flow-=di;
E[i^1].flow+=di;
return di;
}
}
}
return 0;
}

Luogu 2764 最小路径覆盖问题 / Libre 6002 「网络流 24 题」最小路径覆盖 (网络流,最大流)的更多相关文章

  1. LibreOJ #6002. 「网络流 24 题」最小路径覆盖

    #6002. 「网络流 24 题」最小路径覆盖 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:Special Judge 上传者: 匿名 提交提交记录统计讨论测 ...

  2. [LOJ#6002]「网络流 24 题」最小路径覆盖

    [LOJ#6002]「网络流 24 题」最小路径覆盖 试题描述 给定有向图 G=(V,E).设 P 是 G 的一个简单路(顶点不相交)的集合.如果 V 中每个顶点恰好在 P 的一条路上,则称 P 是  ...

  3. LOJ6002 - 「网络流 24 题」最小路径覆盖

    原题链接 Description 求一个DAG的最小路径覆盖,并输出一种方案. Solution 模板题啦~ Code //「网络流 24 题」最小路径覆盖 #include <cstdio&g ...

  4. Libre 6013 「网络流 24 题」负载平衡 (网络流,最小费用最大流)

    Libre 6013 「网络流 24 题」负载平衡 (网络流,最小费用最大流) Description G 公司有n 个沿铁路运输线环形排列的仓库,每个仓库存储的货物数量不等.如何用最少搬运量可以使n ...

  5. Libre 6008 「网络流 24 题」餐巾计划 (网络流,最小费用最大流)

    Libre 6008 「网络流 24 题」餐巾计划 (网络流,最小费用最大流) Description 一个餐厅在相继的N天里,第i天需要Ri块餐巾(i=l,2,-,N).餐厅可以从三种途径获得餐巾. ...

  6. Libre 6003 「网络流 24 题」魔术球 (网络流,最大流)

    Libre 6003 「网络流 24 题」魔术球 (网络流,最大流) Description 假设有n根柱子,现要按下述规则在这n根柱子中依次放入编号为 1,2,3,4......的球. (1)每次只 ...

  7. Libre 6010「网络流 24 题」数字梯形 (网络流,最大费用最大流)

    Libre 6010「网络流 24 题」数字梯形 (网络流,最大费用最大流) Description 给定一个由n 行数字组成的数字梯形如下图所示.梯形的第一行有m 个数字.从梯形的顶部的m 个数字开 ...

  8. Libre 6004 「网络流 24 题」圆桌聚餐(网络流,最大流)

    Libre 6004 「网络流 24 题」圆桌聚餐(网络流,最大流) Description 假设有来自n个不同单位的代表参加一次国际会议.每个单位的代表数分别为 ri.会议餐厅共有m张餐桌,每张餐桌 ...

  9. 【刷题】LOJ 6002 「网络流 24 题」最小路径覆盖

    题目描述 给定有向图 \(G = (V, E)\) .设 \(P\) 是 \(G\) 的一个简单路(顶点不相交)的集合.如果 \(V\) 中每个顶点恰好在 \(P\) 的一条路上,则称 \(P\) 是 ...

随机推荐

  1. 20155210 Exp5 MSF基础应用

    Exp5 MSF基础应用 一个主动攻击实践,MS08-067 首先利用msfconsole启用msf终端 然后利用search MS08-067搜索漏洞,会显示相应漏洞模块 如图: 根据上图,我们输入 ...

  2. python变量名感悟

    我感悟的是python的变量名其实就可以理解为C/C++中的指针! 1.python的变量在使用之前必须赋值,就像指针在使用之前不能为空. 2.python的内存可以用del释放,C++可以用dele ...

  3. 探索sklearn | K均值聚类

    1 K均值聚类 K均值聚类是一种非监督机器学习算法,只需要输入样本的特征 ,而无需标记. K均值聚类首先需要随机初始化K个聚类中心,然后遍历每一个样本,将样本归类到最近的一个聚类中,一个聚类中样本特征 ...

  4. lnmp如何实现伪静态,默认目录伪静态

    LNMP一键安装包一直是我小内存VPS的首选安装环境,因为它占用资源少,性能高.最新发布的lnmp0.7还增加了对LNMPA的支持,LNMPA使用Nginx作为前端服务能够更快更及时的静态页面.js. ...

  5. 【ORACLE】oracle11g单实例安装

    -- 上传安装包 p13390677_112040_Linux-x86-64_1of7.zip p13390677_112040_Linux-x86-64_2of7.zip -- 解压安装包 unzi ...

  6. js的各种正则表达式

    验证各种手机包括成都"028-"开头的座机号验证 if (!(/^(16[8]|13[0-9]|15[0|3|6|7|8|9]|18[7])\d{8}|(028-)\d{7}$/. ...

  7. Jq_Js_Js、Jq获取浏览器和屏幕各种高度宽度

    $(document).ready(function()         {alert($(window).height()); //浏览器当前窗口可视区域高度alert($(document).he ...

  8. NodeMCU学习(三) : 进入网络世界

    把NodeMCU连接到路由器网络上 NodeMCU可以被配置为Station模式和softAP模式或者Station + AP模式,当它被配置为Station模式时,就可以去连接Access Poin ...

  9. 安装Ubuntu后要做的事

    优化 删除libreoffice sudo apt-get remove libreoffice-common 删除Amazon sudo apt-get remove unity-webapps-c ...

  10. Unity3d Transform.forward和Vector3.forward的区别!

    在Unity中有两个forward,一个是Transform.forward一个是Vector3.forward. 对于Vector3来说,它只是缩写.没有其它任何含义. Vector3.forwar ...