最小路径覆盖问题 2011-12-29
算法实现题8-3 最小路径覆盖问题(习题 8-13)
´问题描述:
给定有向图 G=(V,E)。设 P 是 G 的一个简单路(顶点不相交)的集合。如果 V 中每个
顶点恰好在 P 的一条路上,则称 P是 G 的一个路径覆盖。P 中路径可以从 V 的任何一个顶
点开始,长度也是任意的,特别地,可以为0。G 的最小路径覆盖是G 的所含路径条数最少
的路径覆盖。
设计一个有效算法求一个有向无环图G 的最小路径覆盖。
编程任务:
对于给定的给定有向无环图G,编程找出 G的一个最小路径覆盖。
´数据输入:
由文件input.txt提供输入数据。文件第1 行有 2个正整数 n和 m。n是给定有向无环图
G 的顶点数, m是G 的边数。 接下来的 m行, 每行有 2 个正整数 i和 j, 表示一条有向边(i,j)。
´结果输出:
程序运行结束时,将最小路径覆盖输出到文件 output.txt 中。从第 1 行开始,每行输出
一条路径。文件的最后一行是最少路径数。
输入文件示例
input.txt
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
输出文件示例
output.txt
1 4 7 10 11
2 5 8
3 6 9
3
_______________________________
把每个点i拆成 xi和yi,如果有边{i, j},则 建一条权值为1的{yi,xj}的边.
最后建边 {s,xi}和{yi,t}权值都为1。
因为当每个点各自为一条简单路时,最小路径覆盖即为n,所以有两个点连条边,那么最小路径覆盖可以减1,所以最后n-flow 即为答案
_______________________________
1 Program Stone; 2 var i,n,m,le,s,t,flow:longint; 3 head,dis,vh,cur,last,pre:array[0..20000]of longint; 4 next,date,point:array[-20000..20000]of longint; 5 procedure add(x,y:longint); 6 begin 7 inc(le); 8 date[le]:=1; 9 point[le]:=y; 10 next[le]:=head[x]; 11 head[x]:=le; 12 point[-le]:=x; 13 next[-le]:=head[y]; 14 head[y]:=-le; 15 end; 16 procedure init; 17 var i,j,k:longint; 18 begin 19 readln(n,m); 20 s:=0;t:=2*n+1; 21 for i:=1 to m do 22 begin 23 readln(j,k); 24 add(j,k+n); 25 end; 26 for i:=1 to n do 27 begin 28 add(s,i); 29 add(i+n,t); 30 end; 31 end; 32 procedure print; 33 var i,j:longint; 34 begin 35 for i:=n+1 to n+n do 36 if pre[i]=0 then 37 begin 38 j:=i-n; 39 while j>0 do 40 begin 41 write(j,' '); 42 j:=last[j]-n; 43 end; 44 writeln; 45 end; 46 writeln(n-flow); 47 end; 48 function min(a,b:longint):longint; 49 begin 50 if a<b then min:=a else min:=b; 51 end; 52 function aug(x,nf:longint):longint; 53 var i,j,l,d,minh,ins:longint; 54 begin 55 if x=t then exit(nf); 56 l:=nf; 57 i:=cur[x]; 58 while i<>0 do 59 begin 60 if (date[i]>0)and(dis[x]=dis[point[i]]+1) then 61 begin 62 cur[x]:=i; 63 d:=aug(point[i],min(l,date[i])); 64 if (d>0)and(x<=n)and(x>s) then begin last[x]:=point[i];pre[point[i]]:=1;end; 65 dec(date[i],d); 66 inc(date[-i],d); 67 dec(l,d); 68 if (dis[s]=t+1)or(l=0) then exit(nf-l); 69 end; 70 i:=next[i]; 71 end; 72 if l=nf then 73 begin 74 minh:=t; 75 i:=head[x]; 76 while i<>0 do 77 begin 78 if (date[i]>0)and(dis[point[i]]<minh) then begin minh:=dis[point[i]];ins:=i;end; 79 i:=next[i]; 80 end; 81 cur[x]:=ins; 82 dec(vh[dis[x]]); 83 if vh[dis[x]]=0 then dis[s]:=t+1; 84 dis[x]:=minh+1; 85 inc(vh[dis[x]]); 86 end; 87 aug:=nf-l; 88 end; 89 Begin 90 assign(input,'prog83.in');assign(output,'prog83.out'); 91 reset(input);rewrite(output); 92 init; 93 for i:=s to t do cur[i]:=head[i]; 94 vh[0]:=t+1; 95 while dis[s]<t+1 do inc(flow,aug(0,maxint)); 96 print; 97 close(input);close(output); 98 end.
_____MildTheorem