AC日记——最小路径覆盖问题 洛谷 P2764
题目描述
«问题描述:
给定有向图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 )最大流。
«编程任务:
对于给定的给定有向无环图G,编程找出G的一个最小路径覆盖。
输入输出格式
输入格式:
件第1 行有2个正整数n和m。n是给定有向无环图G 的顶点数,m是G 的边数。接下来的m行,每行有2 个正整数i和j,表示一条有向边(i,j)。
输出格式:
从第1 行开始,每行输出一条路径。文件的最后一行是最少路径数。
输入输出样例
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
1 4 7 10 11
2 5 8
3 6 9
3
说明
1<=n<=150,1<=m<=6000
思路:
网络流24题之一;
还是那条性质,求最小割;
每条有向边的u,v加边都是u,v+n;
求出最大流,ans=n-最大流;
然后,我们在求最大流的时候把匹配的点和边做标记以输出路径;
来,上代码:
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm> #define INF 0x7ffffff using namespace std; struct EdgeType {
int to,next,flow;
};
struct EdgeType edge[]; int if_z,n,m,cnt=,head[],s=,t=;
int deep[],next[],ans; bool if_[]; char Cget; inline void in(int &now)
{
now=,if_z=,Cget=getchar();
while(Cget>''||Cget<'')
{
if(Cget=='-') if_z=-;
Cget=getchar();
}
while(Cget>=''&&Cget<='')
{
now=now*+Cget-'';
Cget=getchar();
}
now*=if_z;
} inline void edge_add(int u,int v,int w)
{
edge[++cnt].to=v,edge[cnt].flow=w,edge[cnt].next=head[u],head[u]=cnt;
edge[++cnt].to=u,edge[cnt].flow=,edge[cnt].next=head[v],head[v]=cnt;
} bool BFS()
{
queue<int>que;
memset(deep,-,sizeof(deep));
que.push(s),deep[s]=;
while(!que.empty())
{
int pos=que.front();
for(int i=head[pos];i;i=edge[i].next)
{
if(deep[edge[i].to]<&&edge[i].flow>)
{
deep[edge[i].to]=deep[pos]+;
if(edge[i].to==t) return true;
que.push(edge[i].to);
}
}
que.pop();
}
return false;
} int flowing(int now,int flow)
{
if(now==t||flow==) return flow;
int oldflow=;
for(int i=head[now];i;i=edge[i].next)
{
if(deep[edge[i].to]!=deep[now]+||edge[i].flow==) continue;
int pos=flowing(edge[i].to,min(flow,edge[i].flow));
if(pos>)
{
next[now]=edge[i].to;
if(edge[i].to>n) if_[edge[i].to-n]=true;
}
flow-=pos;
oldflow+=pos;
edge[i].flow-=pos;
edge[i^].flow+=pos;
if(flow==) return oldflow;
}
return oldflow;
} void dinic()
{
while(BFS()) ans-=flowing(s,INF);
} int main()
{
in(n),in(m);int u,v;ans=n;
for(int i=;i<=m;i++)
{
in(u),in(v);
edge_add(u,v+n,INF);
}
for(int i=;i<=n;i++)
{
edge_add(s,i,);
edge_add(i+n,t,);
}
dinic();
for(int i=;i<=n;i++)
{
if(if_[i]) continue;
int pos=i;
printf("%d",pos);
while(next[pos])
{
if(next[pos]>n) next[pos]-=n;
printf(" %d",next[pos]);
pos=next[pos];
}
printf("\n");
}
printf("%d\n",ans);
return ;
}
AC日记——最小路径覆盖问题 洛谷 P2764的更多相关文章
- AC日记——无线网络发射器选址  洛谷  P2038
		
题目描述 随着智能手机的日益普及,人们对无线网的需求日益增大.某城市决定对城市内的公共场所覆盖无线网. 假设该城市的布局为由严格平行的129 条东西向街道和129 条南北向街道所形成的网格状,并且相邻 ...
 - AC日记——校门外的树 洛谷 P1047
		
题目描述 某校大门外长度为L的马路上有一排树,每两棵相邻的树之间的间隔都是1米.我们可以把马路看成一个数轴,马路的一端在数轴0的位置,另一端在L的位置:数轴上的每个整数点,即0,1,2,……,L,都种 ...
 - AC日记——小A的糖果 洛谷七月月赛
		
小A的糖果 思路: for循环贪心: 代码: #include <bits/stdc++.h> using namespace std; #define maxn 100005 #defi ...
 - AC日记——矩阵取数游戏 洛谷 P1005
		
矩阵取数游戏 思路: dp+高精: 代码: #include <bits/stdc++.h> using namespace std; #define ll long long struc ...
 - AC日记——红色的幻想乡 洛谷 P3801
		
红色的幻想乡 思路: 线段树+容斥原理: 代码: #include <bits/stdc++.h> using namespace std; #define maxn 100005 #de ...
 - AC日记——妖梦拼木棒 洛谷 P3799
		
妖梦拼木棒 思路: 神特么题: 代码: #include <bits/stdc++.h> using namespace std; #define mod 1000000007LL int ...
 - AC日记——妖梦斩木棒 洛谷 P3797
		
妖梦斩木棒 思路: 略坑爹: 代码: #include <bits/stdc++.h> using namespace std; #define maxn 200005 #define m ...
 - AC日记——[SDOI2009]HH去散步 洛谷 P2151
		
[SDOI2009]HH去散步 思路: 矩阵快速幂递推(类似弗洛伊德): 给大佬跪烂-- 代码: #include <bits/stdc++.h> using namespace std; ...
 - AC日记——聪明的质监员 洛谷 P1314
		
聪明的质监员 思路: 二分: 代码: #include <bits/stdc++.h> using namespace std; #define maxn 200005 #define l ...
 
随机推荐
- Unity基础-脚本的加载与编译顺序
			
脚本的加载与编译顺序 C#是以Assembly(汇编集)为一个基本单元组织代码的,dll就是一个assembly,dll之间有加载以来顺序 Assets/*.dll Stamdard Assets/* ...
 - Voyager下的Media Manager文件管理与Menu Builder
			
Media Manager 默认存储位置在storage/app/public 上传文件,新建文件夹,移动,重命名,删除等等等功能 Menu Builder 创建新的Main菜单 创建一个shop菜单 ...
 - 【netbeans】netbeans utf-8编码
			
首先,在你的netbeans的安装文件夹里面找到etc这个文件夹,打开,在里面找到netbeans.conf这个文件,打开,找到这一句netbeans_default_options="-J ...
 - Python基础(五)——闭包与lambda的结合
			
(1)变量的域 要了解闭包需要先了解变量的域,也就是变量在哪一段“上下文”是有效的(类似局部变量和全局变量的区别),举一个很简单的例子.(例子不重要,就是涉及闭包就要时刻关注这个域) def test ...
 - JAVA基础篇—String和StringBuffer
			
区别: (1)String类对象为不可变对象,一旦你修改了String对象的值,隐性重新创建了一个新的对象,释放原String对象,StringBuffer类对象为可修改对象,可以通过append() ...
 - TCP的三次握手和四次握手
			
三次握手(建立连接) 首先,服务器进程(B)先创建传控制块TCB(用来存储连接信息,如连接表,发送和接收序号等),准备接收客户进程(A)的请求.然后服务器进程处于LISTEN(收听)状态,等待客户的连 ...
 - 重新造轮子之静态链接2(Static linking)
			
有了上一篇的基础, 这次写一个我们已经滚瓜烂熟的C程序 helloworld .只不过这次我们不能用到到C语言中的main()函数. 实验环境: linux 编译器: gcc 编辑器:Vim 1. ...
 - 《小团团团队》第九次团队作业:Beta冲刺与验收准备
			
项目 内容 这个作业属于哪个课程 任课教师博客主页链接 这个作业的要求在哪里 实验十三 团队作业9:Beta冲刺与团队项目验收 团队名称 小团团团队 作业学习目标 (1)掌握软件黑盒测试技术:(2)学 ...
 - luogu3371 【模板】单源最短路径 dijkstra堆优化
			
#include <algorithm> #include <iostream> #include <cstring> #include <cstdio> ...
 - webdriver高级应用- 右键另存为下载文件
			
1.要使用右键另存,需要先按照第三方工具AutoIt: 链接: https://pan.baidu.com/s/12aBBhOOTmyQpH9hukt0XGA 密码: fcdk 2.创建一个名为loa ...