最小路径覆盖问题 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

_______________________________

把每个点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.

 

posted on 2016-03-02 20:32  Yesphet  阅读(180)  评论(0编辑  收藏  举报