Luogu 2764 最小路径覆盖问题 / Libre 6002 「网络流 24 题」最小路径覆盖 (网络流,最大流)
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 题」最小路径覆盖 (网络流,最大流)的更多相关文章
- LibreOJ #6002. 「网络流 24 题」最小路径覆盖
#6002. 「网络流 24 题」最小路径覆盖 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:Special Judge 上传者: 匿名 提交提交记录统计讨论测 ...
- [LOJ#6002]「网络流 24 题」最小路径覆盖
[LOJ#6002]「网络流 24 题」最小路径覆盖 试题描述 给定有向图 G=(V,E).设 P 是 G 的一个简单路(顶点不相交)的集合.如果 V 中每个顶点恰好在 P 的一条路上,则称 P 是 ...
- LOJ6002 - 「网络流 24 题」最小路径覆盖
原题链接 Description 求一个DAG的最小路径覆盖,并输出一种方案. Solution 模板题啦~ Code //「网络流 24 题」最小路径覆盖 #include <cstdio&g ...
- Libre 6013 「网络流 24 题」负载平衡 (网络流,最小费用最大流)
Libre 6013 「网络流 24 题」负载平衡 (网络流,最小费用最大流) Description G 公司有n 个沿铁路运输线环形排列的仓库,每个仓库存储的货物数量不等.如何用最少搬运量可以使n ...
- Libre 6008 「网络流 24 题」餐巾计划 (网络流,最小费用最大流)
Libre 6008 「网络流 24 题」餐巾计划 (网络流,最小费用最大流) Description 一个餐厅在相继的N天里,第i天需要Ri块餐巾(i=l,2,-,N).餐厅可以从三种途径获得餐巾. ...
- Libre 6003 「网络流 24 题」魔术球 (网络流,最大流)
Libre 6003 「网络流 24 题」魔术球 (网络流,最大流) Description 假设有n根柱子,现要按下述规则在这n根柱子中依次放入编号为 1,2,3,4......的球. (1)每次只 ...
- Libre 6010「网络流 24 题」数字梯形 (网络流,最大费用最大流)
Libre 6010「网络流 24 题」数字梯形 (网络流,最大费用最大流) Description 给定一个由n 行数字组成的数字梯形如下图所示.梯形的第一行有m 个数字.从梯形的顶部的m 个数字开 ...
- Libre 6004 「网络流 24 题」圆桌聚餐(网络流,最大流)
Libre 6004 「网络流 24 题」圆桌聚餐(网络流,最大流) Description 假设有来自n个不同单位的代表参加一次国际会议.每个单位的代表数分别为 ri.会议餐厅共有m张餐桌,每张餐桌 ...
- 【刷题】LOJ 6002 「网络流 24 题」最小路径覆盖
题目描述 给定有向图 \(G = (V, E)\) .设 \(P\) 是 \(G\) 的一个简单路(顶点不相交)的集合.如果 \(V\) 中每个顶点恰好在 \(P\) 的一条路上,则称 \(P\) 是 ...
随机推荐
- 《FPGA设计技巧与案例开发详解-第二版》全套资料包
本人参与写的一本书(TimeQuest一章由我所写),希望大家多多支持: 全书配套资料上传各大网盘资料中附送大量源码,你值得拥有--<FPGA设计技巧与案例开发详解-第二版>全套资料包-V ...
- vs编译器好多下划波浪线但不报错
解决办法:项目属性->c/c++->常规->附加包含目录->$(ProjectDir): $(ProjectDir) 项目的目录(定义形式:驱动器 + 路径):包括尾部的反斜杠 ...
- Spring Boot(十一):Spring Boot 中 MongoDB 的使用
MongoDB 是最早热门非关系数据库的之一,使用也比较普遍,一般会用做离线数据分析来使用,放到内网的居多.由于很多公司使用了云服务,服务器默认都开放了外网地址,导致前一阵子大批 MongoDB 因配 ...
- DFA化简
首先是未化简DFA的转换表 NFA状态 DFA状态 a b {0,1,2,4,7} A B C {1,2,3,4,6,7,8} B B D {1,2,4,5,6,7} C B C {1,2,4,5,6 ...
- shellcode 编码技术
在很多漏洞利用场景中, shellcode 的内容将会受到限制. 例如你不能输入 \x00 这个字符,编辑框不能输入 \x0d \x0a这样的字符 所以需要完成 shellcode 的逻辑,然后使用编 ...
- Ubuntu环境如何上传项目到GitHub网站?
http://blog.csdn.net/ajianyingxiaoqinghan/article/details/70544159
- [2017BUAA软工助教]结对项目小结
2017BUAA结对项目小结 一.作业链接 http://www.cnblogs.com/jiel/p/7604111.html 二.评分细则 1.注意事项 按时间完成并提交--正常评分 晚交一周以内 ...
- C#获取每月最后一天或者最末一天的方法
/// <summary> /// 取得某月的第一天 /// </summary> /// <param name="datetime">要取得 ...
- javascript 函数的几种声明函数以及应用环境
本页只列出常用的几种方式,当然还有比如new Function()以及下面三种的组合. 1.函数式声明 例子:function sum(a,b){ return a+b; }; 2.函数表达式声明(匿 ...
- TensorFlow图像识别(物体分类)入门教程
本文主要介绍了如何使用TensorFlow环境运行一个最基本的图像分类器(Win10系统).源码地址https://github.com/sourcedexter/tfClassifier/tree/ ...