pascal中级教程第五章图.docx

上传人:b****3 文档编号:6249488 上传时间:2023-05-09 格式:DOCX 页数:23 大小:47.47KB
下载 相关 举报
pascal中级教程第五章图.docx_第1页
第1页 / 共23页
pascal中级教程第五章图.docx_第2页
第2页 / 共23页
pascal中级教程第五章图.docx_第3页
第3页 / 共23页
pascal中级教程第五章图.docx_第4页
第4页 / 共23页
pascal中级教程第五章图.docx_第5页
第5页 / 共23页
pascal中级教程第五章图.docx_第6页
第6页 / 共23页
pascal中级教程第五章图.docx_第7页
第7页 / 共23页
pascal中级教程第五章图.docx_第8页
第8页 / 共23页
pascal中级教程第五章图.docx_第9页
第9页 / 共23页
pascal中级教程第五章图.docx_第10页
第10页 / 共23页
pascal中级教程第五章图.docx_第11页
第11页 / 共23页
pascal中级教程第五章图.docx_第12页
第12页 / 共23页
pascal中级教程第五章图.docx_第13页
第13页 / 共23页
pascal中级教程第五章图.docx_第14页
第14页 / 共23页
pascal中级教程第五章图.docx_第15页
第15页 / 共23页
pascal中级教程第五章图.docx_第16页
第16页 / 共23页
pascal中级教程第五章图.docx_第17页
第17页 / 共23页
pascal中级教程第五章图.docx_第18页
第18页 / 共23页
pascal中级教程第五章图.docx_第19页
第19页 / 共23页
pascal中级教程第五章图.docx_第20页
第20页 / 共23页
亲,该文档总共23页,到这儿已超出免费预览范围,如果喜欢就下载吧!
下载资源
资源描述

pascal中级教程第五章图.docx

《pascal中级教程第五章图.docx》由会员分享,可在线阅读,更多相关《pascal中级教程第五章图.docx(23页珍藏版)》请在冰点文库上搜索。

pascal中级教程第五章图.docx

pascal中级教程第五章图

第五章图

5.1医院设置

源程序名hospital.?

?

?

(pas,c,cpp)

可执行文件名hospital.exe

输入文件名hospital.in

输出文件名hospital.out

【问题描述】

设有一棵二叉树,如图5-1:

1

/\

2

3

/\

4

5

其中,圈中的数字表示结点中居民的人口。

圈边上数字表示结点编号,现在要求在某个结点上建立一个医院,使所有居民所走的路程之和为最小,同时约定,相邻接点之间的距离为l。

如上图中,若医院建在:

【输入】

第一行一个整数n,表示树的结点数。

(n≤100)

接下来的n行每行描述了一个结点的状况,包含三个整数,整数之间用空格(一个或多个)分隔,其中:

第一个数为居民人口数;第二个数为左链接,为0表示无链接;第三个数为右链接。

【输出】

一个整数,表示最小距离和。

【样例】

hospital.inhospital.out

581

1323

400

1245

2000

4000

【知识准备】

图的遍历和最短路径。

【算法分析】

本题的求解任务十分明了:

求一个最小路径之和。

根据题意,对n个结点,共有n个路径之和:

用记号Si表示通向结点i的路径之和,则

,其中Wj为结点j的居民数,g(i,j)为结点j到结点i的最短路径长度。

下面表中反映的是样例的各项数据:

j

g(i,j)

i

1

2

3

4

5

Si

1

0

1

1

2

2

0×13+1×4+1×12+2×20+2×40=136

2

1

0

2

3

3

1×13+0×4+2×12+3×20+3×40=217

3

1

2

0

1

1

1×13+2×4+0×12+1×20+1×40=81

4

2

3

1

0

2

2×13+3×4+1×12+0×20+2×40=130

5

2

3

1

2

0

2×13+3×4+1×12+2×20+0×40=90

从表中可知S3=81最小,医院应建在3号居民点,使得所有居民走的路径之和为最小。

由此可知,本题的关键是求g[i,j],即图中任意两点间的最短路径长度。

求任意两点间的最短路径采用下面的弗洛伊德(Floyd)算法。

(1)数据结构:

w:

array[1..100]oflonging;描述个居民点人口数

g:

array[1..100,1..100]oflongint初值为图的邻接矩阵,最终为最短路径长度

(2)数据的读入:

本题数据结构的原形为二叉树,数据提供为孩子标识法,分支长度为1,建立带权图的邻接矩阵,分下面两步:

①g[i,j]←Max{Max为一较大数,表示结点i与j之间无直接相连边}

②读入n个结点信息:

fori:

=1tondo

begin

g[i,j]:

=0;

readln(w[i],l,r);

ifl>0thenbegin

g[i,l]:

=l;g[l,i]:

=l

end;

ifr>0thenbegin

g[i,r]:

=l;g[r,i]:

=l

end;

(3)弗洛伊德算法求任意两点间的最短路径长度

fork:

=1tondo

fori:

=1tondo

ifi<>kthenforj:

=1tondo

if(i<>j)and(k<>j)and(g[i,k]+g[k,j]

=g[i,k]+g[k,j];

(4)求最小的路程和min

min:

=maxlongint;

fori:

=1tondo

begin

sum:

=0;

forj:

=1tondosum:

=sum+w[i]*g[i,j];

ifsum

=sum;

end;

(5)输出

writeln(min);

5.2工程规划

源程序名work.?

?

?

(pas,c,cpp)

可执行文件名work.exe

输入文件名work.in

输出文件名work.out

【问题描述】

造一幢大楼是一项艰巨的工程,它是由n个子任务构成的,给它们分别编号1,2,…,n(5≤n≤1000)。

由于对一些任务的起始条件有着严格的限制,所以每个任务的起始时间T1,T2,…,Tn并不是很容易确定的(但这些起始时间都是非负整数,因为它们必须在整个工程开始后启动)。

例如:

挖掘完成后,紧接着就要打地基;但是混凝土浇筑完成后,却要等待一段时间再去掉模板。

这种要求就可以用M(5≤m≤5000)个不等式表示,不等式形如Ti-Tj≤b代表i和j的起始时间必须满足的条件。

每个不等式的右边都是一个常数b,这些常数可能不相同,但是它们都在区间(-100,100)内。

你的任务就是写一个程序,给定像上面那样的不等式,找出一种可能的起始时间序列T1,T2,…,Tn,或者判断问题无解。

对于有解的情况,要使最早进行的那个任务和整个工程的起始时间相同,也就是说,T1,T2,…,Tn中至少有一个为0。

【输入】

第一行是用空格隔开的两个正整数n和m,下面的m行每行有三个用空格隔开的整数i,j,b对应着不等式Ti-Tj≤b。

【输出】

如果有可行的方案,那么输出N行,每行都有一个非负整数且至少有一个为0,按顺序表示每个任务的起始时间。

如果没有可行的方案,就输出信息“NOSOLUTION”。

【样例1】

work.inwork.out

580

1202

15–15

2514

3151

414

43–1

53–1

54–3

【样例2】

work.inwork.out

55NOSOLUTION

12–3

15–1

25–1

51–5

414

【算法分析】

本题是一类称为约束满足问题的典型问题,问题描述成n个子任务的起始时间Ti及它们之间在取值上的约束,求一种满足所有约束的取值方法。

将工程的n个子任务1,2,…,n作为一有向图G的n个顶点,顶点Vi(i=1,…,n)的关键值为子任务i的起始时间Ti,我们并不需要关心顶点之间的弧及其弧长,而是要确定顶点的关键值Ti的取值,满足所有的约束条件。

本题的约束条件由m个不等式Ti-Tj≤b给出,这样的有向图称为约束图。

为了确定每一个Ti的值,先假设某一个子任务的起始时间为零,如设Tj=0,则其余子任务的起始时间Ti相对于T1可设置其起始时间为一区间[-maxt,maxt]。

下面分析不等式Ti-Tj≤b。

此不等式可变形为如下两种形式:

(1)Ti≤Tj+b意味Ti的最大值为Tj+b;

(2)Tj≥Ti-b意味Tj的最大值为Ti-b;

因此,根据题中给出的m个不等式,逐步调整各个Ti的最小值和最大值。

设high[i]为Ti当前的最大值,low[i]为Ti当前的最小值。

high[j]为Tj当前的最大值,low[j]为Tj当前的最小值。

若high[i]-high[j]>b,则high[i]=high[j]+b(根据Ti≤Tj+b),

若low[i]-low[j]

以上的调整终止视下列两种情况而定:

(1)对所有的不等式Ti-Tj≤b,不再有high[i]或low[j]的调整;

(2)若存在high[i]

根据以上思路,先建立约束图,每个结点代表一个起始时间值,并记录其可能的取值范围:

数组high,low:

array[1..maxn]oflongint;{n个子任务起始时间的取值范围}

high[1]=0;low[1]=0;{设置n个起始时间的初值,其中Ti=0}

fori:

=2tondobegin

high[i]:

=maxt;{Ti的上界}

low[i]:

=-maxt;{Tj的下界}

end;

约束条件(m个不等式)用记录数组表示:

type{不等式结构}

Tinequ=record

i,j,b:

longint;

end;

var

arrinequ:

array[1..maxm]ofTinequ;{存放m个不等式}

利用约束条件,逐一调整每一个起始时间的取值范围,直到无法调整为止。

主要算法如下:

flag:

=true;{调整状态标记}

noans:

=false;{解的有无标记}

while(flag)do{进行约束传递,根据不等式调整各个起始时间值}

begin

flag:

=false;

fork:

=1tomdo

witharrinequ[k]do

begin

if(high[i]-high[j]>b)thenbeginhigh[i]:

=high[j]+b;flag:

=true;end;{调整Ti的上界}

if(low[i]-low[j]>b)thenbeginlow[j]:

=low[i]-b;flag:

=true;end;{调整Tj的下界}

if(low[i]>high[i])or(low[j]>high[j])

thenbegin{无法满足当前不等式,则调整终止}

noans:

=true;{问题无解noans=true}

flag:

=false;

break;

end;

end;

end;

下面以样例说明:

【样例1】

8个不等式如下

序号

1

2

3

4

5

6

7

8

i

1

1

2

3

4

4

5

5

j

2

5

5

1

1

3

3

4

b

0

-1

1

5

4

-1

-3

-3

顶点的关键值Ti的调整记录:

初值

第1轮调整

第2轮调整

第3轮调整

high[1]

0

0

0

0

low[1]

0

0

0

0

high[2]

100000

100000

2

2

low[2]

-10000

2

2

2

high[3]

100000

5

5

5

low[3]

-10000

4

5

5

high[4]

100000

4

4

4

low[4]

-10000

4

4

4

high[5]

100000

1

1

1

low[5]

-10000

1

1

1

调整状态

有变化

有变化

无变化

【样例2】

5个不等式如下

编号

1

2

3

4

5

i

1

1

2

5

4

j

2

5

5

1

1

b

-3

-1

-1

-5

4

顶点关键值Ti的调整记录:

初值

第一轮调整

第二轮调整

1

high

0

0

low

0

0

2

high

100000

99999

low

-10000

3

3

high

100000

10000

low

-10000

-10000

4

high

100000

4

low

-10000

-10000

5

high

100000

-5

low

-10000

1

调整情况

high[5]

经第一轮调整,调整过程终止,即问题无解。

从样例2所给不等式也可看出,因为:

T1-T2≤-3,→T2>T1

T2-T5≤-1,→T5>T2

T5-T1≤-5,→T1>T5

这三个不等式不能同时成立,因此问题无解。

5.3服务器储存信息问题

源程序名servers.?

?

?

(pas,c,cpp)

可执行文件名servers.exe

输入文件名servers.in

输出文件名servers.out

【问题描述】

Byteland王国准备在各服务器间建立大型网络并提供多种服务。

网络由n台服务器组成,用双向的线连接。

两台服务器之间最多只能有一条线直接连接,同时,每台服务器最多只能和10台服务器直接连接,但是任意两台服务器间必然存在一条路径将它们连接在一起。

每条传输线都有一个固定传输的速度。

δ(V,W)表示服务器V和W之间的最短路径长度,且对任意的V有δ(V,V)=0。

有些服务器比别的服务器提供更多的服务,它们的重要程度要高一些。

我们用r(V)表示服务器V的重要程度(rank)。

rank越高的服务器越重要。

每台服务器都会存储它附近的服务器的信息。

当然,不是所有服务器的信息都存,只有感兴趣的服务器信息才会被存储。

服务器V对服务器W感兴趣是指,不存在服务器U满足,r(U)>r(W)且δ(V,U)<δ(V,W)。

举个例子来说,所有具有最高rank的服务器都会被别的服务器感兴趣。

如果V是一台具有最高rank的服务器,由于δ(V,V)=0,所以V只对具有最高rank的服务器感兴趣。

我们定义B(V)为V感兴趣的服务器的集合。

我们希望计算所有服务器储存的信息量,即所有服务器的|B(V)|之和。

Byteland王国并不希望存储大量的数据,所以所有服务器存储的数据量(|B(V)|之和)不会超过30n。

你的任务是写一个程序,读入Byteland王国的网络分布,计算所有服务器存储的数据量。

【输入】

第一行两个整数n和m,(1≤n≤30000,1≤m≤5n)。

n表示服务器的数量,m表示传输线的数量。

接下来n行,每行一个整数,第i行的整数为r(i)(1≤r(i)≤10),表示第i台服务器的rank。

接下来m行,每行表示各条传输线的信息,包含三个整数a,b,t(1≤t≤1000,1≤a,b≤n,a≠b)。

a和b是传榆线所连接的两台服务器的编号,t是传输线的长度。

【输出】

一个整数,表示所有服务器存储的数据总量,即|B(V)|之和。

【样例】

servers.inservers.out

439

2

3

1

1

1430

2320

3420

注:

B

(1)={1,2},B

(2)={2},B(3)={2,3},B(4)={1,2,3,4}。

【知识准备】

Dijkstra算法,及其O((n+e)log2n)或O(nlog2n+e)的实现。

【算法分析】

本题的难点在于问题的规模。

如果问题的规模在100左右,那么这将是一道非常容易的题目。

因为O(n3)的算法是很容易想到的:

(1)求出任意两点间的最短路径,时间复杂度为O(n3);

(2)枚举任意两点,根据定义判断一个节点是否对另一个节点感兴趣,时间复杂度为O(n3)。

当然,对于30000规模的本题来说,O(n3)的算法是绝对不可行的,即便降到O(n2)也不行,只有O(nlog2n)或O(n)是可以接受的。

既然现在可以得到的算法与要求相去甚远,要想一鼓作气得到一个可行的算法似乎就不是那么容易了。

我们不妨先来看看我们可以做些什么。

判断一个节点V是否对节点W感兴趣,就是要判断是否存在一个rank大于r(W)的节点U,δ(V,U)<δ(V,W)。

所以,节点V到某个特定的rank的节点(集合)的最短距离是一个非常重要的值。

如果我们可以在O(nlog2n)时间内求出所有节点到特定rank的节点(集合)的最短距离,我们就成功地完成了算法的一个重要环节。

用Dijkstva算法反过来求特定rank的节点(集合)到所有点的最短距离——以所有特定rank的节点为起点(rank=1,2,3,…或10),求这一点集到所有点的最短距离。

由于图中与每个点关联的边最多只有10条,所以图中的边数最多为5n。

用PriorityQueue(Heap,WinnerTree或FibonacciHeap等)来实现Dijkstra算法,时间复杂度为O((n+e)log2n)(用FibonacciHeap实现,更确切的时间复杂度是O(nlog2n+e))。

这里,e=5n,因而求一遍最短路径的时间复杂度为O(nlog2n)。

由于1≤rank≤10,每个rank都要求一遍最短路径,所以求出每个节点到所有rank的最短路径长度的时间复杂度为O(10*(5+1)nlog2n),即O(nlog2n)。

求出所有点到特定rank的节点(集合)的最短距离,就完成了判断任意节点V对W是否感兴趣的一半工作。

另一半是求任意节点V到W的最短距离。

前面求节点到rank的最短距离时,利用的是rank范围之小——只有10种,以10个rank集合作起点,用Dijkstra算法求10次最短路径。

但是,如果是求任意两点的最短路径,就不可能只求很少次数的最短路径了。

一般来说,求任意两点最短路径是Ω(n2)的(这只是一个很松的下界),这样的规模已经远远超出了可承受的范围。

但是,要判断V对W是否感兴趣,δ(V,W)又是必须求的,所以n次Dijkstra算法求最短路径肯定是逃不掉的(或者也可以用一次Floyd算法代替,但是时间复杂度一样,可认为等价)。

那么,我们又能从哪里来降这个时间复杂度呢?

题目中提到:

所有服务器储存的数据量(|B(V)|之和)不会超过30n。

这就是说,最多只存在30n对(V,W)满足V对W感兴趣。

所以,就本题来说,我们需要处理的点对最少可能只有30n个,求最短距离的下界也就变成Ω(30n)=Ω(n)了(当然,这也只是很松的下界)。

虽说下界是Ω(n),其实我们只需要有O(nlog2n)的算法就可以满足要求了。

从前面估算下界的过程中我们也看到,计算在下界中的代价都是感兴趣的点对(一个节点对另一个节点感兴趣),其余部分为不感兴趣的点对。

我们如果想降低时间复杂度,就要避免不必要的计算,即避免计算不感兴趣的点对的最短路径。

我们来看当V对W不感兴趣时的情况。

根据定义,δ(V,W)>δ(V,r(W)+1)。

如果是以W为起点,用Dijkstra算法求最短路径的话。

当扩展到V时,发现V对W不感兴趣,即δ(V,W)>δ(V,r(W)+1)。

那么,如果再由V扩展求得到U的最短路径,则:

δ(U,W)=δ(V,W)+δ(U,V),

δ(U,r(W)+1)=δ(V,r(W)+1)+δ(U,V),

由于δ(V,W)>δ(V,r(W)+1),

所以δ(V,W)+δ(U,V)>δ(V,r(W)+1)+δ(U,V),即δ(U,W)>δ(U,r(W)+1)

所以,U对W也不感兴趣。

因此,如果以W为起点,求其他点到W的最短路径,以判断其他点是否对W感兴趣,当扩展到对W不感兴趣的节点时,就可以不继续扩展下去了(只扩展对W感兴趣的节点)。

我们知道,所有感兴趣的点对不超过30n。

因此,以所有点作起点,用Dijkstra算法求最短路径的时间复杂度可由平摊分析得为O(30(n+e)log2n)=O(30(n+5n)log2n)=O(nlog2n)。

由此,我们看到判断一节点是否对另一节点感兴趣,两个关键的步骤都可以在O(nlog2n)时间内完成。

当然算法的系数是很大的,不过由于n不大,这个时间复杂度还是完全可以承受的。

下面就总结一下前面得到的算法:

(1)分别以rank=1,2,…,10的节点(集合)作为起点,求该节点(集合)到所有点的最短距离(其实也就是所有点到该节点(集合)的最短距离);

(2)以每个点作为起点,求该点到所有点的最短距离。

当求得某节点的最短距离的同时根据求得的最短距离和该节点到rank大于起点的节点(集合)的最短距离,判断该节点是否对起点感兴趣。

如果感兴趣,则找到一对感兴趣的点对,否则,停止扩展该节点,因为该节点不可能扩展出对起点感兴趣的节点。

总结解题的过程,可以发现解决本题的关键有三点:

一是稀疏图,正因为图中边比较稀疏所以我们可以用Dijkstra+PriorityQueue的方法将求最短路径的时间复杂度降为O(nlog2n);二是rank的范围很小,rank的范围只有10,所以我们只用了10次Dijkstra算法就求得了所有点到特定rank的最短距离;三是感兴趣的点对只有很少,由于感兴趣的点对只有30n,我们通过只计算感兴趣点对的最短路径,将求点与点间最短路径的时间复杂度降到了O(nlog2n)。

这三点,只要有一点没有抓住。

本题就不可能得到解决。

5.4间谍网络(AGE)

源程序名age.?

?

?

(pas,c,cpp)

可执行文件名age.exe

输入文件名age.in

输出文件名age.out

【问题描述】

由于外国间谍的大量渗入,国家安全正处于高度的危机之中。

如果A间谍手中掌握着关于B间谍的犯罪证据,则称A可以揭发B。

有些间谍收受贿赂,只要给他们一定数量的美元,他们就愿意交出手中掌握的全部情报。

所以,如果我们能够收买一些间谍的话,我们就可能控制间谍网中的每一分子。

因为一旦我们逮捕了一个间谍,他手中掌握的情报都将归我们所有,这样就有可能逮捕新的间谍,掌握新的情报。

我们的反间谍机关提供了一份资料,色括所有已知的受贿的间谍,以及他们愿意收受的具体数额。

同时我们还知道哪些间谍手中具体掌握了哪些间谍的资料。

假设总共有n个间谍(n不超过3000),每个间谍分别用1到3000的整数来标识。

请根据这份资料,判断我们是否有可能控制全部的间谍,如果可以,求出我们所需要支付的最少资金。

否则,输出不能被控制的一个间谍。

【输入】

输入文件age.in第一行只有一个整数n。

第二行是整数p。

表示愿意被收买的人数,1≤p≤n。

接下来的p行,每行有两个整数,第一个数是一个愿意被收买的间谍的编号,第二个数表示他将会被收买的数额。

这个数额不超过20000。

紧跟着一行只有一个整数r,1≤r≤8000。

然后r行,每行两个正整数,表示数对(A,B),A间谍掌握B间谍的证据。

【输出】

答案输出到age.out。

如果可以控制所有间谍,第一行输出YES,并在第二行输出所需要支付的贿金最小值。

否则输出NO,并在第二行输出不能控制的间谍中,编号最小的间谍编号。

【样例1】

age.inage.out

3YES

2110

110

2100

2

13

23

【样例2】

age.inage.out

4NO

23

1100

4200

2

12

34

【算法分析】

根据题中给出的间谍的相互控制关系,建立有向图。

找出有向图中的所有强连通分量,用每个强连通分量

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 小学教育 > 语文

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2