题目描述

«问题描述:

给定有向图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 行开始,每行输出一条路径。文件的最后一行是最少路径数。

解题思路:

转换一下思路,需要覆盖,那么最多就需要点数条路径。

然后发现,有些路径可以合并,而且每合并一个点集,就少一条路径。

那么什么样的点可以合并呢,就是一条边相连的。

那么将一个点分裂成两个一个用于接受合并,一个用来提供合并。

相连的点,从起点的提供指向终点的接受,流量为$inf$

每个点都可以是起点终点所以向源汇点连$1$的边。

最大流最后拿n减掉就好了。

代码:

 #include<cstdio>
#include<cstring>
#include<algorithm>
const int oo=0x3f3f3f3f;
namespace stb{
template<class tnt>
class queue{
public:
queue(){h=,t=;}
int nxt(int x){if(x+==)return ;return x+;}
void push(tnt x){t=nxt(t);l[t]=x;return ;}
bool empty(void){return nxt(t)==h;}
tnt front(void){return l[h];}
void clear(void){h=,t=;}
void pop(void){h=nxt(h);}
private:
tnt l[];
int h,t;
};
};
struct pnt{
int hd;
int now;
int lyr;
int nxt;
bool nos;
}p[];
struct ent{
int twd;
int lst;
int vls;
}e[];
int cnt;
int n,m;
int s,t;
stb::queue<int>Q;
void ade(int f,int t,int v)
{
cnt++;
e[cnt].twd=t;
e[cnt].vls=v;
e[cnt].lst=p[f].hd;
p[f].hd=cnt;
return ;
}
bool Bfs(void)
{
Q.clear();
for(int i=;i<=n*+;i++)
p[i].lyr=;
p[s].lyr=;
Q.push(s);
while(!Q.empty())
{
int x=Q.front();
Q.pop();
for(int i=p[x].hd;i;i=e[i].lst)
{
int to=e[i].twd;
if(p[to].lyr==&&e[i].vls>)
{
p[to].lyr=p[x].lyr+;
if(to==t)
return true;
Q.push(to);
}
}
}
return false;
}
int Dfs(int x,int fll)
{
if(x==t)
return fll;
for(int &i=p[x].now;i;i=e[i].lst)
{
int to=e[i].twd;
if(p[to].lyr==p[x].lyr+&&e[i].vls>)
{
int ans=Dfs(to,std::min(fll,e[i].vls));
if(ans>)
{
e[i].vls-=ans;
e[((i-)^)+].vls+=ans;
p[x].nxt=to;
if(x!=s)
p[to-n].nos=true;
return ans;
}
}
}
return ;
}
void Dinic(void)
{
int ans=;
while(Bfs())
{
for(int i=;i<=*n+;i++)
p[i].now=p[i].hd;
int dlt;
while(dlt=Dfs(s,oo))
ans+=dlt;
}
for(int i=;i<=n;i++)
{
if(!p[i].nos)
{
for(int j=i;j!=t-n&&j>;j=p[j].nxt-n)
printf("%d ",j);
puts("");
}
}
printf("%d\n",n-ans);
return ;
}
int main()
{
scanf("%d%d",&n,&m);
s=n*+,t=n*+;
for(int i=;i<=n;i++)
{
ade(s,i,);
ade(i,s,);
ade(i+n,t,);
ade(t,n+i,);
}
for(int i=;i<=m;i++)
{
int a,b;
scanf("%d%d",&a,&b);
ade(a,b+n,oo);
ade(b+n,a,);
}
Dinic();
return ;
}

LuoguP2764 最小路径覆盖问题(最大流)的更多相关文章

  1. [luoguP2764] 最小路径覆盖问题(最大流 || 二分图最大匹配)

    传送门 可惜洛谷上没有special judge,不然用匈牙利也可以过的,因为匈牙利在增广上有一个顺序问题,所以没有special judge就过不了了. 好在这个题的测试数据比较特殊,如果是网络流的 ...

  2. [题解] LuoguP2764 最小路径覆盖问题

    传送门 好久没做网络流方面的题发现自己啥都不会了qwq 题意:给一张有向图,让你用最少的简单路径覆盖所有的点. 考虑这样一个东西,刚开始,我们有\(n\)条路径,每条路径就是单一的一个点,那么我们的目 ...

  3. P2764 [网络流24题]最小路径覆盖问题[最大流]

    地址 这题有个转化,求最少的链覆盖→即求最少联通块. 设联通块个数$x$个,选的边数$y$,点数$n$个 那么有 $y=n-x$   即  $x=n-y$ 而n是不变的,目标就是在保证每个点入度.出度 ...

  4. 【wikioi】1904 最小路径覆盖问题(最大流+坑人的题+最小路径覆盖)

    http://wikioi.com/problem/1904/ 这题没看数据的话是一个大坑(我已报告官方修复了),答案只要求数量,不用打印路径...orz 最小路径覆盖=n-最大匹配,这个我在说二分图 ...

  5. BZOJ.1927.[SDOI2010]星际竞速(无源汇上下界费用流SPFA /最小路径覆盖)

    题目链接 上下界费用流: /* 每个点i恰好(最少+最多)经过一次->拆点(最多)+限制流量下界(i,i',[1,1],0)(最少) 然后无源汇可行流 不需要源汇. 注: SS只会连i',求SS ...

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

    Luogu 2764 最小路径覆盖问题 / Libre 6002 「网络流 24 题」最小路径覆盖 (网络流,最大流) Description 给定有向图G=(V,E).设P是G的一个简单路(顶点不相 ...

  7. 洛谷 P2764 最小路径覆盖问题【最大流+拆点+路径输出】

    题目链接:https://www.luogu.org/problemnew/show/P2764 题目描述 «问题描述: 给定有向图G=(V,E).设P 是G 的一个简单路(顶点不相交)的集合.如果V ...

  8. BZOJ1927: [Sdoi2010]星际竞速(最小费用最大流 最小路径覆盖)

    题意 题目链接 Sol 看完题不难想到最小路径覆盖,但是带权的咋做啊?qwqqq 首先冷静思考一下:最小路径覆盖 = \(n - \text{二分图最大匹配数}\) 为什么呢?首先最坏情况下是用\(n ...

  9. LibreOJ 6002 最小路径覆盖(最大流)

    题解:最小路径覆盖=总点数减去最大匹配数,拆点,按照每条边前一个点连源点,后一个点连汇点跑最大流,即可跑出最大匹配数,然后减一减就可以了~ 代码如下: #include<queue> #i ...

随机推荐

  1. spring context对象

    在 java 中, 常见的 Context 有很多, 像: ServletContext, ActionContext, ServletActionContext, ApplicationContex ...

  2. 在 Ubuntu 18.04 LTS 无头服务器上安装 Oracle VirtualBox

    作者: Sk 译者: LCTT qhwdw | 2018-10-12 01:59 本教程将指导你在 Ubuntu 18.04 LTS 无头服务器上,一步一步地安装 Oracle VirtualBox. ...

  3. MFC的学习路线

    首先,MFC是比较难的!比C#和VB要难得多.MFC是基于C++的.首先C++必须熟悉.MFC主要是学习里面的控件的使用. 建议学习路线: 1. 易语言中文编程从入门到精通: https://deta ...

  4. Centos7不修改默认交换分区下添加交换分区

    交换分区介绍 Linux系统中的交换分区是当物理内存(RAM)被充满时,作为物理内存的缓存来使用. 当系统需要更多的内存资源而物理内存已经充满,内存中不活跃的页就会被移动到交换分区上. 交换分区位于硬 ...

  5. Bash 基础特性

    命令别名  alias 显示当前shell中定义的所有别名  alias 别名='原始命令'  unalias 别名 取消定义的别名在命令前加\使用命令本身,而不是别名(或者使用绝对路径执行命令使用命 ...

  6. 说说Kindle那些事

    已经不记得是什么时候在哪里听过kindle这玩意的了,反正最开始买kindle还是大四上学期,貌似是2012-9-30,那时候是整个大学最闲的时候,不知道哪天闲的蛋疼一冲动就买了个kindle4黑色款 ...

  7. 阿里云主机centos设置虚拟内存

    http://blog.csdn.net/luwei42768/article/details/51241758 https://my.oschina.net/u/2306127/blog/65726 ...

  8. MYSQL 更新时间自己主动同步与创建时间默认值共存问题

    本文作者:苏生米沿 本文地址:http://blog.csdn.net/sushengmiyan/article/details/50326259 在使用SQL的时候,希望在更新数据的时候自己主动填充 ...

  9. 试图切换控制addChildViewController、_transitionFromViewController

    试图切换能够用transitionFromViewController. 步骤: View Controller中能够加入多个sub view,在须要的时候显示出来: 能够通过viewControll ...

  10. 五大最受欢迎的BUG管理系统

    Google在中国大陆遭遇变故做出临时性的退出大陆市场,也使非常多忠实的用户受到小小的挫折,以本公司为例.原本的BUG都是记录在google的 EXCEL在线文档中,由于常常性的打不开.測试和开发组在 ...