数据结构第20次课章节名称7.5.2关键路径7.6.1从某个源点到其余各顶点的最短路径目的要求1.理解并掌握关键路径的基本思想和步骤,对给定的带权有向图能够求出关键路径。2.理解并掌握最短路径的含义、Dijkstra算法的基本思想和时间性能,能够根据Dijkstr算法画出给定有向图的求单源最短路径的过程示意图。主要内容与时间概算序号主要内容时间概算1AOV-网10分2关键路径45分3最短路径的含义5分4Dijkstra算法的基本思想40分共计100分重点难点重点:1.关键路径的概念和实际应用,求带权有向图的关键路径;2.最短路径的含义、Dijkstra算法的基本思想和时间性能。难点:1.求带权有向图的关键路径;2.Dijkstra算法的基本思想,求有向图的单源最短路径方法手段采用教员课堂讲授、学员实际操作的方法实施教学。授课中应对于重/难点作详细分析,并结合课堂讲授的内容实施上机实验教学任务。(续表)课堂提问1.如何缩短完成整项工程所需时间?2.如何在计算机中求得最短路径?本次课内容总结1.关键路径的概念和实际应用,求带权有向图的关键路径;2.最短路径的含义、Dijkstra算法的基本思想和时间性能,如何求有向图单源最短路径。思考题作业题试对下图所示的AOE网络,解答下列问题。(1)这个工程最早可能在什么时间结束。(2)求每个事件的最早开始时间Ve[i]和最迟开始时间Vl[I]。(3)求每个活动的最早开始时间e()和最迟开始时间l()。(4)确定哪些活动是关键活动。画出由所有关键活动构成的图,指出哪些活动加速可使整个工程提前完成。参考资料《数据结构辅导与提高》,徐孝凯编著,清华大学出版社《数据结构习题解答与考试指导》,梁作娟等编著,清华大学出版社授课内容7.5.2关键路径对整个工程和系统,人们关心的是两个方面的问题:一)工程能否顺利进行(对AOV网进行拓扑排序)二)估算整个工程的完成所必须的最短时间(对AOE网求关键路径)1.AOE-网与AOV-网相对应的是AOE-网(ActivityOnEdge),即边表示活动的网。AOE-网是一个带权的有向无环图,其中,顶点表示事件(Event),弧表示活动,权表示活动持续的时间。通常,AOE-网可用来估算工程的完成时间。例:下图是一个假想的有11项活动的AOE-网。其中有9个事件v1,v2,…,v9,每个事件表示在它之前的活动已经完成,在它之后的活动可以开始。如v1表示整个工程开始,v9表示整个工程结束,v5表示a4和a5已经完成,a7和a8可以开始。与每个活动相联系的数是执行该活动所需的时间。比如,活动a1需要6天,a2需要4天等。和AOV-网不同,对AOE-网有待研究的问题是:(1)完成整项工程至少需要多少时间?(2)哪些活动是影响工程进度的关键?2.关键路径由于在AOE-网中有些活动可以并行地进行,所以完成工程的最短时间是从开始点到完成点的最长路径的长度(这里所说的路径长度是指路径上各活动持续时间之和,不是路径上弧的数目)。路径长度最长的路径叫做关键路径(CriticalPath)。备注:回顾假设开始点是v1,从v1到vi的最长路径长度叫做事件vi的最早发生时间。这个时间决定了所有以vi为尾的弧所表示的活动的最早开始时间。我们用e(i)表示活动ai的最早开始时间。还可以定义一个活动的最迟开始时间l(i),这是在不推迟整个工程完成的前提下,活动ai最迟必须开始进行的时间。两者之差l(i)-e(i)意味着完成活动ai的时间余量。我们把l(i)=e(i)的活动叫做关键活动。显然,关键路径上的所有活动都是关键活动,因此提前完成非关键活动并不能加快工程的进度。因此,分析关键路径的目的是辨别哪些是关键活动,以便争取提高关键活动的工效,缩短整个工期。例:上图中从v1到v9的最长路径是(v1,v2,v5,v8,v9),路径长度是18,即v9的最早发生时间是18。解决方案:由上分析可知,辨别关键活动就是要找e(i)=l(i)的活动。为了求得AOE-网中活动的e(i)和l(i),首先求事件的最早发生时间ve(j)和最迟发生时间vl(j)。如果活动ai由弧j,k表示,其持续时间记为dut(j,k),则有如下关系:e(i)=ve(j)(1)l(i)=vl(k)-dut(j,k)求ve(j)和vl(j)需分两步进行:(1)从ve(0)开始向前递推其中,T是所有以第j个顶点为头的弧的结合。(2)从vl(n-1)=ve(n-1)起向后递推其中,S是所有以第i个顶点为尾的弧的集合。这两个递推公式的计算必须分别在拓扑有序和逆拓扑有序的前提下进行。也就是说ve(j-1)必须在vj的所有前驱的最早发生时间求得之后才能确定,而vl(j-1)则必须在vj的所有后继的最迟发生时间求得之后才能确定。因此,可以在拓扑排序的基础上计算ve(j-1)和vl(j-1)。所以,求关键路径的算法:(1)输入e条弧(j,k),建立AOE网的存储结构。(2)从源点v0出发,令ve[0]=0按拓扑有序求其余各顶点的最早发生时ve[i](1≤i≤n-1)。如得到的拓扑序列中顶点个数小于网中顶点数n,则说明网中存在环,不能求关键路径,算法终止;否则执行步骤(3)。(3)从汇点vn出发,令vl[n-1]=ve[n-1],按逆拓扑有序求其余各顶点的最迟发生时间vl[i](n-2≥i≥2);(4)根据各顶点的ve和vl值,求每条弧s的最早开始时间e(s)和最迟开始时间l(s)。若某条弧满足条件e(s)=l(s),则为关键活动。计算顶点的ve值是在拓扑排序的过程中进行的。计算ve需对拓扑排序的算法作如下修改:(1)在拓扑排序之前设初值,令ve(i)=0(0=in-1);(2)在算法中增加一个计算vj的直接后继vk的最早发生时间的操作:若ve(j)+dut(j,k)ve(k),则ve(k)=ve(j)+dut(j,k);(3)为了能按逆拓扑有序序列的顺序计算各顶点的vl值,需记下在拓扑排序的过程中求得的拓扑有序序列,则需要在拓扑排序算法中,增设一个栈以记录拓扑有序序列,则在计算求得各顶点的ve值之后,从栈顶至栈底便为逆拓扑有序序列。先将拓扑排序算法改写成算法1,则算法2便为求关键路径的算法。StatusTopologicalOrder(ALGraphG,Stack&T){//有向网G采用邻接表,求各顶点事件最早发生时间ve(全局变量)//T为拓扑序列顶点栈,s为零入度顶点栈。若G无回路,返回G的一拓扑序列,函数值为OK,否则ERROR。FindInDegree(G,indegree);//对各顶点求入度for(i=0;iG.vexnum;++i)//建零入度顶点栈Sif(!indegree[i])Push(S,i)//入度为0者进栈InitStack(T);count=0;ve[0..G.vexnum-1]=0;//初始化while(!StackEmpty(S)){//j号顶点入T栈并计数Pop(S,j);Push(T,j);++count;for(p=G.vertices[j].firstarc;p;p=p-nextarc){k=p—adjvex;//对i号顶点的每个邻接点的入度减lif(--indegree[k]==0)Push(S,k);//若入度减为0,则入栈if(ve[j]+*(p-info)ve[k])ve[k]=ve[j]+*(p-info);}//for*(p-info)=dut(j,k)}//whileif(countG.vexnum)returnERROR;//该有向网有回路elsereturnOK;}//TopologicalOrder算法1StatusCriticalPath(ALGraphG){//G为有向网,输出G的各项关键活动if(!TopologicalOrder(G,T))returnERROR;//初始化顶点事件的最迟发生时间vl[0..G.vexnum-1]=ve[0..C.vexnum-1];//按拓扑逆序求各顶点的vl值while(!StackEmpty(T))for(Pop(T,j),p=G.vertices[j].firstarc;p;p=p-nextarc){k=p-adjvex;dut=*(p—info);//duti,kif(vl[k]-dutvl[j])vl[j]=vl[k]-dut;}//forfor(j=0;jG.vexnum;++j)//求ee,el和关键活动for(p=G.vertices[j];p;p=p-nextarc){k=p-adjvex;dut=*(p—info);ee=ve[j];el=v1[k]-dut;tag=(ee==e1)?‘*’:’’;printf(j,k,dut,ee,el,tag);//输出关键活动}}//CriticalPath算法2由于逆拓扑排序必定在网中无环的前提下进行,则亦可利用DFS函数,在退出DFS函数之前按公式3计算顶点v的vl值(因为此时v的所有直接后继的vl值都已求出)。实践证明:用AOE-网来估算某些工程完成的时间是非常有用的。关键活动的速度提高是有限度的。只有在不改变网的关键路径的情况下,提高关键活动的速度才有效。另一方面,若网中有几条关键路径,那么,单是提高一条关键路径上的关键活动的速度,还不能导致整个工程缩短工期,而必须提高同时在几条关键路径上的活动的速度。例:7.6最短路径问题背景:假若要在计算机上建立一个交通咨询系统则可采用图的结构来表示实际的交通网络。图中顶点表示城市,边表示城市间的交通。这个咨询系统可以回答旅客提出的各种问题。来看一简单的图的最短路径问题。例:一位旅客要从A城到B城,可能希望选择一条途中中转次数最少的,或交通费用最节省的路线;而对于司机来说,里程和速度则是他们感兴趣的。为了在图上表示有关信息,可对边赋以权,权的值表示两城市间的距离,或途中所需时间,或交通费用等等。此时路径长度的度量就不再是路径上边的数目,而是路径上边的权值之和。考虑到交通图的有向性(如逆水和顺水的船速就不一样),本节将讨论带权有向图,并称路径上的第一个顶点为源点,最后一个顶点为终点。最短路径问题:如果从图中源点出发到达终点的路径可能不止一条,如何找到一条路径使得沿此路径上各边的权值总和达到最小。7.6.1从某个源点到其余各顶点的最短路径问题描述:给定带权有向图G和源点v,求从v到G中其余各顶点的最短路径。限定各边上的权值大于或等于0。例:带权有向图G中从v0到其余各顶点之间的最短路径如图所示。如何在计算机中求得最短路径?迪杰斯特拉(Dijkstra)提出了一个按路径长度递增的次序,逐步产生最短路径的算法。首先求出长度最短的一条最短路径,然后参照它求出长度次短的一条最短路径,依次类推,直到从顶点v到其它各顶点的最短路径全部求出为止。用反证法来证明:假设此路径上有一个顶点不在S中(vp∈V-S),则说明存在一条终点不在S而长度比此路径短的路径。但是,这是不可能的。因为我们是按路径长度递增的次序来产生各最短路径的,故长度比此路径短的所有路径均已产生,它们的终点必定在S中,即假设不成立。Dijkstra算法需一个顶点集合,初始时集合内只有源点V0,以后陆续将已求得最短路径的顶点加入到集合中,直到全部顶点都进入。集合可用一维数组S来表示,凡集合S以外的顶点,其相应数组元素S[i]为0,否则为1。另需一个一维数组dist,每个顶点对应数组的一个单元,记录从源点到其他各顶点当前的最短路径长度,初值为dist[i]=cost[V0][i],i=1…n。数组dist中的数据随着算法的逐步进行要不断地修改。算法在进行中,都是从S之外的顶点集中选一顶点w,使dist[w]的值最小。于是从源点到达w只通过S中的顶点,把w加入S中,并调整dist中记录的从源点到集合中每个顶点v的距离:从原来的dist[v]和dist[w]+cost[w][v]中,选择较小的值作为新的dist[v]。重复上述,直到S