计算拓扑序列

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

所谓拓扑序列,就是有向图的最长路径问题,如果图中存在环,则最长路径是无法求得的,所以有拓扑序列的有向图不可以存在环。具体定义如下:

给出有向图G=(V,E),若结点的线形序列V1,V2,...Vn满足条件:对于i,j(1≤j

【拓扑排序主要思想】

有向图可以拓扑排序的条件是:图中没有环。

具体方法:

⑴ 从图中选择一个入度为0的点加入拓扑序列。

⑵ 从图中删除该结点以及它的所有出边(即与之相邻点入度减1)。

反复执行这两个步骤,直到所有结点都已经进入拓扑序列。

【实例:士兵排队问题】

有n个士兵(1≤n≤26),依次编号为A,B,C,...,队列训练时,指挥官要把一些士兵从高到矮排成一行。但现在指挥官不能直接获得每个人的身高信息,只能获得“p1比p2高”这样的比较结果,记作(p1>p2)。例如A>B,B>D,F>D,对应的排队方案有三个:AFBD,FABD,ABFD

【输入】

k行,每行a b,表示a>b

【输出】

一个可行的排队方案

【输入样例】

A B

B D

F D

【输出样例】

ABFD

program soldier_sort;

var

w:array['A'..'Z','A'..'Z'] of 0..1;

d:array['A'..'Z'] of integer; {记录顶点入度的数组}

s:set of 'A'..'Z';

a,b,ch:char;

m,n:string;

i,j,k:integer;

begin

assign(input,'tuopu.in');

reset(input);

assign(output,'tuopu.out');

rewrite(output);

s:=[];

while not eof(input) do

begin

readln(a,ch,b);

s:=s+[a,b]; {计算士兵名集合}

w[a,b]:=1;

d[b]:=d[b]+1; {累计顶点b的入度}

end;

m:='';

for a:='A' to 'Z' do

if a in s

then m:=m+a; {产生士兵名字符集}

k:=length(m); {求得士兵人数}

n:=''; {拓扑序列初始为空}

for i:=1 to k do

begin

j:=1;

while (d[m[j]]>0) and (j<=k) do {搜索第i个入度为0的士兵的顶点序号j} j:=j+1;

if j>k {若不存在入度为0的顶点,则无法拓扑排序失败} then begin

writeln('Fault!');

break;

end;

n:=n+m[j]; {入度为0的顶点进入拓扑序列n}

a:=m[j]; {删去顶点j}

d[a]:=maxint;

for j:=1 to k do {与a相连的顶点入度减1}

if w[a,m[j]]>0

then d[m[j]]:=d[m[j]]-1;

end;{for}

writeln(n);

close(input);

close(output);

end.

相关文档
最新文档