您的位置:首页 > 其它

最小路径覆盖问题 2011-12-29

2016-03-02 20:32 337 查看
算法实现题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 即为答案

_______________________________

Program Stone;
var i,n,m,le,s,t,flow:longint;
head,dis,vh,cur,last,pre:array[0..20000]of longint;
next,date,point:array[-20000..20000]of longint;
procedure add(x,y:longint);
begin
inc(le);
date[le]:=1;
point[le]:=y;
next[le]:=head[x];
head[x]:=le;
point[-le]:=x;
next[-le]:=head[y];
head[y]:=-le;
end;
procedure init;
var i,j,k:longint;
begin
readln(n,m);
s:=0;t:=2*n+1;
for i:=1 to m do
begin
readln(j,k);
add(j,k+n);
end;
for i:=1 to n do
begin
add(s,i);
add(i+n,t);
end;
end;
procedure print;
var i,j:longint;
begin
for i:=n+1 to n+n do
if pre[i]=0 then
begin
j:=i-n;
while j>0 do
begin
write(j,' ');
j:=last[j]-n;
end;
writeln;
end;
writeln(n-flow);
end;
function min(a,b:longint):longint;
begin
if a<b then min:=a else min:=b;
end;
function aug(x,nf:longint):longint;
var i,j,l,d,minh,ins:longint;
begin
if x=t then exit(nf);
l:=nf;
i:=cur[x];
while i<>0 do
begin
if (date[i]>0)and(dis[x]=dis[point[i]]+1) then
begin
cur[x]:=i;
d:=aug(point[i],min(l,date[i]));
if (d>0)and(x<=n)and(x>s) then begin last[x]:=point[i];pre[point[i]]:=1;end;
dec(date[i],d);
inc(date[-i],d);
dec(l,d);
if (dis[s]=t+1)or(l=0) then exit(nf-l);
end;
i:=next[i];
end;
if l=nf then
begin
minh:=t;
i:=head[x];
while i<>0 do
begin
if (date[i]>0)and(dis[point[i]]<minh) then begin minh:=dis[point[i]];ins:=i;end;
i:=next[i];
end;
cur[x]:=ins;
dec(vh[dis[x]]);
if vh[dis[x]]=0 then dis[s]:=t+1;
dis[x]:=minh+1;
inc(vh[dis[x]]);
end;
aug:=nf-l;
end;
Begin
assign(input,'prog83.in');assign(output,'prog83.out');
reset(input);rewrite(output);
init;
for i:=s to t do cur[i]:=head[i];
vh[0]:=t+1;
while dis[s]<t+1 do inc(flow,aug(0,maxint));
print;
close(input);close(output);
end.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: