[网络流24题] 最小路径覆盖问题
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[网络流24题] 最小路径覆盖问题相关的知识,希望对你有一定的参考价值。
问题描述:
给定有向图G=(V,E)。设P是G的一个简单路(顶点不相交)的集合。如果V中每个顶点恰好在P的一条路上,则称P是G的一个路径覆盖。P中路径可以从V的任何一个顶点开始,长度也是任意的,特别地,可以为0。G的最小路径覆盖是G的所含路径条数最少的路径覆盖。设计一个有效算法求一个有向无环图G的最小路径覆盖。
提示:
设V={1,2,... ,n},构造网络G1=(V1,E1)如下:
每条边的容量均为1。求网络G1的(x0,y0)最大流。
编程任务:
对于给定的给定有向无环图G,编程找出G的一个最小路径覆盖。
数据输入:
由文件input.txt提供输入数据。文件第1行有2个正整数n和m。n是给定有向无环图G的顶点数,m是G的边数。接下来的m行,每行有2个正整数i 和j,表示一条有向边(i,j)。
结果输出:
程序运行结束时,将最小路径覆盖输出到文件output.txt中。从第1行开始,每行输出一条路径。文件的最后一行是最少路径数。
题解:
最小路径覆盖,建图方法:把所有点分别加入二分图中的x集和y集,如果i节点可以连向j,就让在x集中的i连向一条在y集的j,权值为inf。然后让S连向x集,权值为1。让y集连向T,权值为1。跑网络流,路径的个数就是点的总数减去最大流的值。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cstring> 5 #include<cmath> 6 #include<algorithm> 7 #include<queue> 8 #include<vector> 9 using namespace std; 10 const int inf=1e9; 11 const int maxn=500,maxm=60000; 12 inline int read(){ 13 int x=0,f=1;char ch=getchar(); 14 while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();} 15 while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();} 16 return x*f; 17 } 18 int N,M,S,T,ANS; 19 struct Edge{ 20 int to,next,rest; 21 }e[maxm]; 22 int head[maxn]; 23 int ecnt=1; 24 inline void addedge(int x,int y,int r){ 25 e[++ecnt].to=y; e[ecnt].rest=r; e[ecnt].next=head[x]; head[x]=ecnt; 26 e[++ecnt].to=x; e[ecnt].rest=0; e[ecnt].next=head[y]; head[y]=ecnt; 27 } 28 int dis[maxn]; 29 30 bool BFS(){ 31 memset(dis,0,sizeof(dis)); 32 dis[S]=1; 33 static queue<int> Q; 34 while(!Q.empty()) Q.pop(); 35 Q.push(S); 36 while(!Q.empty()){ 37 int x=Q.front(); Q.pop(); 38 for(int i=head[x];i;i=e[i].next){ 39 int y=e[i].to; 40 if(e[i].rest&&dis[y]==0){ 41 dis[y]=dis[x]+1; 42 Q.push(y); 43 } 44 } 45 } 46 if(dis[T]) return true; 47 return false; 48 } 49 50 int to[maxn]; 51 bool vis[maxn]; 52 int DFS(int x,int flow){ 53 if(x==T) return flow; 54 int now=0,tmp; 55 for(int i=head[x];i;i=e[i].next){ 56 if(e[i].rest&&dis[e[i].to]==dis[x]+1){ 57 tmp=DFS(e[i].to,min(flow-now,e[i].rest)); 58 if(tmp){ 59 to[x]=e[i].to; 60 if(e[i].to-N>0) vis[e[i].to-N]=true; 61 } 62 e[i].rest-=tmp; 63 e[i^1].rest+=tmp; 64 now+=tmp; 65 if(now==flow) return now; 66 } 67 } 68 if(!now) dis[x]=0; 69 return now; 70 } 71 int dinic(){ 72 int ans=0; 73 while(BFS()){ 74 ans+=DFS(S,1e9); 75 } 76 return ans; 77 } 78 int main(){ 79 freopen("path3.in","r",stdin); 80 freopen("path3.out","w",stdout); 81 N=read(); M=read(); 82 S=0; T=2*N+1; 83 for(int i=1,u,v;i<=M;i++){ 84 u=read(); v=read(); 85 addedge(u,N+v,inf); 86 } 87 for(int i=1;i<=N;i++){ 88 addedge(S,i,1); 89 addedge(N+i,T,1); 90 } 91 ANS=N-dinic(); 92 for(int i=1;i<=N;i++){ 93 if(vis[i]==false){//没有连向i的边,i作为起点 94 printf("%d ",i); 95 int tmp=i; 96 while(to[tmp]){ 97 printf("%d ",to[tmp]-N); 98 tmp=to[tmp]-N; 99 } 100 printf("\n"); 101 } 102 } 103 printf("%d\n",ANS); 104 return 0; 105 }
以上是关于[网络流24题] 最小路径覆盖问题的主要内容,如果未能解决你的问题,请参考以下文章