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算法,请移步我的这篇文章

代码

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstdlib>
  4. #include<cstring>
  5. #include<algorithm>
  6. using namespace std;
  7. const int maxN=500;
  8. const int maxM=60000;
  9. const int inf=2147483647;
  10. class Edge
  11. {
  12. public:
  13. int v,flow;
  14. };
  15. int n,m;
  16. int cnt=-1;
  17. int Head[maxN];
  18. int Next[maxM];
  19. Edge E[maxM];
  20. int depth[maxN];
  21. int Q[maxM];
  22. int cur[maxN];
  23. bool vis[maxN];
  24. void Add_Edge(int u,int v,int flow);
  25. bool bfs();
  26. int dfs(int u,int flow);
  27. int main()
  28. {
  29. memset(Head,-1,sizeof(Head));
  30. scanf("%d%d",&n,&m);
  31. for (int i=1;i<=n;i++)
  32. {
  33. Add_Edge(0,i,1);//连接源点与入点
  34. Add_Edge(i+n,2*n+1,1);//连接出点与汇点
  35. }
  36. for (int i=1;i<=m;i++)
  37. {
  38. int u,v;
  39. scanf("%d%d",&u,&v);
  40. Add_Edge(u,v+n,1);//连接u的入点与v的出点
  41. }
  42. while (bfs())
  43. {
  44. for (int i=0;i<=n*2+1;i++)//当前弧优化
  45. cur[i]=Head[i];
  46. while (int di=dfs(0,inf));
  47. }
  48. memset(vis,0,sizeof(vis));
  49. int Ans=0;
  50. for (int i=1;i<=n;i++)//统计路径
  51. {
  52. if (vis[i]==1)
  53. continue;
  54. int now=i;
  55. bool get;
  56. do
  57. {
  58. cout<<now<<" ";
  59. vis[now]=1;
  60. get=0;
  61. for (int i=Head[now];i!=-1;i=Next[i])
  62. if ((E[i].flow==0)&&(E[i].v>n)&&(E[i].v<=2*n))
  63. {
  64. now=E[i].v-n;
  65. get=1;
  66. break;
  67. }
  68. }
  69. while (get==1);
  70. cout<<endl;
  71. Ans++;
  72. }
  73. cout<<Ans<<endl;//输出路径条数
  74. return 0;
  75. }
  76. void Add_Edge(int u,int v,int flow)//加边
  77. {
  78. cnt++;
  79. Next[cnt]=Head[u];
  80. Head[u]=cnt;
  81. E[cnt].v=v;
  82. E[cnt].flow=flow;
  83. cnt++;
  84. Next[cnt]=Head[v];
  85. Head[v]=cnt;
  86. E[cnt].v=u;
  87. E[cnt].flow=0;
  88. }
  89. bool bfs()//bfs求层次图
  90. {
  91. memset(depth,-1,sizeof(depth));
  92. int t=0,h=1;
  93. Q[1]=0;
  94. depth[0]=1;
  95. do
  96. {
  97. t++;
  98. int u=Q[t];
  99. for (int i=Head[u];i!=-1;i=Next[i])
  100. {
  101. int v=E[i].v;
  102. if ((E[i].flow>0)&&(depth[v]==-1))
  103. {
  104. depth[v]=depth[u]+1;
  105. h++;
  106. Q[h]=v;
  107. }
  108. }
  109. }
  110. while (h!=t);
  111. if (depth[n*2+1]==-1)//当汇点不存在层次图中时,说明增广完毕
  112. return 0;
  113. return 1;
  114. }
  115. int dfs(int u,int flow)//dfs增广
  116. {
  117. if (u==n*2+1)
  118. return flow;
  119. for (int &i=cur[u];i!=-1;i=Next[i])
  120. {
  121. int v=E[i].v;
  122. if ((depth[v]==depth[u]+1)&&(E[i].flow>0))
  123. {
  124. int di=dfs(v,min(flow,E[i].flow));
  125. if (di>0)
  126. {
  127. E[i].flow-=di;
  128. E[i^1].flow+=di;
  129. return di;
  130. }
  131. }
  132. }
  133. return 0;
  134. }

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. linux中wget的使用方法介绍

    wget是在Linux下开发的开放源代码的软件,作者是Hrvoje Niksic,后来被移植到包括Windows在内的各个平台上.它有以下功能和特点:(1)支持断点下传功能:这一点,也是网络蚂蚁和Fl ...

  2. In-Memory:内存优化表的DMV

    SQL Server 在执行查询时,自动将活动的相关信息保存在内存中,这些活动信息称作DMV(Dynamic Management View),DMV记录SQL Server实例级别上的活动信息.由于 ...

  3. .NET Core容器化开发系列(一)——Docker里面跑个.NET Core

    前言 博客园中已经有很多如何在Docker里面运行ASP.NET Core的介绍了.本篇主要介绍一些细节,帮助初学的朋友更加深入地理解如何在Docker中运行ASP.NET Core. 安装Docke ...

  4. Inno Setup脚本

    某天夜晚一场狂风暴雨,由于办公室座位旁的窗户没关,笔记本电脑泡了一夜水,无法开机,无奈送修,里面的大量资料也不知道会不会丢失. is的脚本只有重新写了,重新研究了一下检测程序是否正在运行的判断方法,另 ...

  5. 再探Redux Middleware

    前言 在初步了解Redux中间件演变过程之后,继续研究Redux如何将中间件结合.上次将中间件与redux硬结合在一起确实有些难看,现在就一起看看Redux如何加持中间件. 中间件执行过程 希望借助图 ...

  6. codeforces 1141G Privatization of Roads in Treeland

    题目链接:http://codeforces.com/contest/1141/problem/G 题目大意: 给你一个无向连通图.每条边都有颜色,如果存在一个点的临边中有超过两条边颜色相同,这个点就 ...

  7. Python网络数据采集

    一.正则表达式 *     表匹配0次或者多次  a*b* +    表至少一次 [ ]   匹配任意一个 ( )  辨识一个编组 {m,n} m或者n 次 [^]  匹配任意不在中括号里的字符 | ...

  8. c++ 读写功能

    课程作业三 git链接: Operations 感想        这次代码修改的地方主要有,加入了文件读写.读出功能,以及分离函数写到了头文件里.        但是也有很多不足的地方,首先本来想要 ...

  9. VS2013安装及测试

    一.Visual Studio的安装 首先是Visual Studio英文版的安装,安装完成后,为了用的时候方便,我从官网下载Visual Studio 2013的语言包并安装. 二.进行单元测试. ...

  10. teamviewer & commercial-use

    teamviewer & commercial-use https://www.teamviewer.com/zhCN/pricing/commercial-use/ https://www. ...