P2764 最小路径覆盖问题
Posted olinr
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P2764 最小路径覆盖问题相关的知识,希望对你有一定的参考价值。
(color{#0066ff}{题目描述})
给定有向图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的一个最小路径覆盖。
(color{#0066ff}{输入格式})
文件第1 行有2个正整数n和m。n是给定有向无环图G 的顶点数,m是G 的边数。接下来的m行,每行有2 个正整数i和j,表示一条有向边(i,j)。
(color{#0066ff}{输出格式})
从第1 行开始,每行输出一条路径。文件的最后一行是最少路径数。
(color{#0066ff}{输入样例})
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
(color{#0066ff}{输出样例})
1 4 7 10 11
2 5 8
3 6 9
3
(color{#0066ff}{数据范围与提示})
有spj
(color{#0066ff}{题解})
最小路径覆盖=总点数-最大匹配/最大流
拆点,每个点拆成出点和入点
原图中(i o j),则将i的出点和j的入点连边
最后暴力跳就行
#include<cstdio>
#include<iostream>
#include<queue>
#include<cstring>
#include<algorithm>
#include<cmath>
#define _ 0
#define LL long long
inline LL in()
{
LL x=0,f=1; char ch;
while(!isdigit(ch=getchar()))(ch=='-')&&(f=-f);
while(isdigit(ch)) x=x*10+(ch^48),ch=getchar();
return x*f;
}
const int inf=0x7fffffff;
const int max=1050;
int n,m,s,t,cnt=1;
struct node
{
int to,nxt,dis;
node(int to=0,int nxt=0,int dis=0):to(to),nxt(nxt),dis(dis){}
}e[120000];
int head[max],cur[max],dep[max];
std::queue<int> q;
bool vis[max];
inline void add(int from,int to,int dis)
{
e[++cnt]=node(to,head[from],dis);
head[from]=cnt;
}
inline bool bfs()
{
for(int i=s;i<=t;i++) cur[i]=head[i],dep[i]=0;
dep[s]=1;
q.push(s);
while(!q.empty())
{
int tp=q.front(); q.pop();
for(int i=head[tp];i;i=e[i].nxt)
{
int go=e[i].to;
if(!dep[go]&&e[i].dis>0)
{
dep[go]=dep[tp]+1;
q.push(go);
}
}
}
return dep[t];
}
inline int dfs(int x,int change)
{
if(x==t||!change) return change;
int flow=0,ls;
for(int i=cur[x];i;i=e[i].nxt)
{
int go=e[i].to;
cur[x]=i;
if(dep[go]==dep[x]+1&&(ls=dfs(go,std::min(e[i].dis,change))))
{
change-=ls;
flow+=ls;
e[i].dis-=ls;
e[i^1].dis+=ls;
if(!change) break;
}
}
return flow;
}
inline int dinic()
{
int flow=0;
while(bfs()) flow+=dfs(s,inf);
return flow;
}
inline int nxt(int x)
{
for(int i=head[x];i;i=e[i].nxt)
{
int go=e[i].to;
if(go>=n+1&&go<=n+n&&e[i].dis!=inf) return go-n;
}
return 0;
}
inline void print()
{
int ans=dinic();
vis[0]=true;
for(int i=1;i<=n;i++)
{
if(!vis[i])
{
for(int o=i;!vis[o];o=nxt(o))
{
vis[o]=true;
printf("%d ",o);
}
putchar('
');
}
}
printf("%d",n-ans);
}
int main()
{
n=in(),m=in();
s=0,t=(n<<1)+1;
int x,y;
for(int i=1;i<=m;i++) x=in(),y=in(),add(x,y+n,inf),add(y+n,x,0);
for(int i=1;i<=n;i++) add(s,i,1),add(i,s,0),add(i+n,t,1),add(t,i+n,0);
print();
return 0;
}
以上是关于P2764 最小路径覆盖问题的主要内容,如果未能解决你的问题,请参考以下文章