精华内容
下载资源
问答
  • AOE网络关键路径

    2012-07-09 02:54:44
    用C++实现的代码,求AOE网络关键路径,有详细注释
  • 图-----------拓扑排序+AOE网络关键路径

    千次阅读 多人点赞 2013-07-20 02:31:30
    )时间,比如上面的红线部分就是完成最大花费时间,关键路径就是这条长度最长的路径(a1->a4->a7->a10或者 a1->a4->a8->a11[关键路径不唯一] ) (2)问题怎么求解? a . 事件(eVent)的最早(Early)发生时间--- 源点到...
    
    

    1.拓扑排序

    (1)举个例子,要学习某些课程必须先学过一些课程

    用图把这个东东描述出来就变成:

     

    那么,问题来啦,是否可以找到一个序列,使得这个序列上的所有课程都满足:先修课程在后修的课程前面?这样的序列就是拓扑序列.....

    (2)怎么求拓扑序列?

    简单的说是不断去掉没有前驱的点,得到的这些点就是拓扑序列;

    还是上面的例子:

    step1:9没有前驱,去掉(和它相关的边也去掉);

    step2:这时候有8,6,4,三个点没有前驱,随便选一个去掉(这个以随便就说明拓扑序列不唯一喔~)

    ......(下面,你懂的~)

    (3)算法

    要用到没有前驱所以要图的入度;

    上面的模拟过程知道实际上是BFS:

    a.建立入度为零的顶点排队
    b.扫描顶点表,将入度为0的顶点入队;
    c.while(排队不空)

    {
    输出队头结点;
    记下输出结点的数目;
    删去与之关联的出边;
    若有入度为0的结点,入队
    }

    d.若输出结点个数小于总的顶点个数,则输出有环路;

    (4)象征性的贴一小段代码

    void topsort(Adgraph* G)
    {
        queue<int> Q;
        int x,count=0;
        for(int i=1; i<=G->n; i++)
            if(G->Ad[i].indegree==0) Q.push(i);//入度为0的顶点入队
        while(!Q.empty())
        {
            x=Q.front();
            Q.pop();
            cout << G->Ad[x].element;//输出点
            count++;//计数器++
            link *m=G->Ad[x].firstedge;
            while(m!=NULL)
            {
                if((--G->Ad[m->v].indegree)==0) Q.push(m->v) ;
    			//每当去掉顶点,入度--;如果这时候它变成没有前驱的顶点,入队
                m=m->next;
            }
        }
        if (count<G->n) cout<<"图中有环路" << endl;
    }


    2.AOE网络

    (1)AOE是什么东东?

    a. AOE上顶点表示事件,边表示活动,边上的权值表示活动需要的时间,入度为0的点叫做源点(V1),出度为0的点叫做结束点(v9);

    b.我们要解决的问题:从源点到达结束点经过的活动的最大(最大喔!)时间,比如上面的红线部分就是完成最大花费时间,关键路径就是这条长度最长的路径(a1->a4->a7->a10或者a1->a4->a8->a11[关键路径不唯一]

    (2)问题怎么求解?

    a.事件(eVent)的最早(Early)发生时间---源点到这个点的最长路径---VE[j];

    b.事件(eVent)的最迟(Late)发生时间---在保证汇点Vn在VE(n)时刻完成的前提下,事件Vk的允 许的最迟开始时间-----VL(k)

    c.活动(Activity)的最早(Early)开始时间:

    如果这个活动i是由<事件j,事件k>之间的,那么容易知道活动i最早的开始时间和时间j最早的发生时间是一样的

    AE(i) = VE(j);

    d.活动(Activity)的最迟(Late)发生时间:是指在不会引起工期延误的前提下,活动ai允许的最迟开始时间.

    如果这个活动i是由<事件j,事件k>之间的,为不推迟工期,活动i的最迟开始时间AL(i)应该是i的最迟完成时间VL(k)减去i的持续时间,即AL(i) = VL(k) - ACT[j][k];(ACT --activity time)

    e.松弛时间(Share time):就是这个活动最迟开始时间和最早开始时间的差:AL[i]-AE[i]

    松弛时间为0,那么这个活动为关键活动;

    (上面的东东有一个大前提:一个活动开始,那么它之前的活动必须全部完成)

    f.逆拓扑序列:拓扑序列反过来;

    g.怎么样求AE,VE,AL,VL?

    基于上面的定义,我们可以用式子简单表示:

    VE:从VE[1]=0开始向前递推,VE[i]=max{VE[j]+ACT<Vj,Vi>},其中<Vj,Vi>是集合{指向Vi的所有边}中的一个元素;

    VL:从VL[n]=VE[n]开始反向递推,VL[i]=min{VL[j]-ACT<Vi,Vj>},期中<Vi,Vj>是集合{从Vi发出的所有边}中的一个元素;

    AE:活动k用<Vi,Vj>表示,AE[k]=VE[i];

    AL:活动k用<Vi,Vj>表示,AL[k]=AL[j]-ACT<Vi,Vj>
    h.算法

    1.建立邻接表;

    2.从源点出发,令VE[1]=0,按照拓扑顺序求解VE[i](判断有没有环);

    3.从结束点出发,VL[n]=VE[n],按照逆拓扑序列求解VL[i];

    4.求解AE[i],AL[i];

    5.如果是关键活动,输出;

    hint:以上全部是自己YY的,不是按照什么专业术语严格证明的,大家看懂个大概,严格的定义和求解还是看书吧!

    象征性的再贴一段代码~

    //Topsort And AOE   
    #include <iostream>   
    #include<stack>   
    #include<queue>   
    #include<cstdio>   
    using namespace std;  
    struct link  
    {  
        int v;//事件编号   
        int count;//活动的编号   
        int weight;//活动的时间   
        link * next;  
    };  
    struct node  
    {  
        int indegree;//入度   
        char element;//事件   
        struct link* firstedge;  
    };//头结点   
    struct Adgraph  
    {  
        int n,e;  
        struct node Ad[101];  
    };//邻接表   
    void Create_AOE(struct Adgraph* G)  
    {  
        int k,i,j,t;  
        cin >> G->n >> G->e;//节点和边   
        for (k=1; k<=G->n; k++)  
        {  
            cin >> G->Ad[k].element;  
            G->Ad[k].firstedge=NULL;  
            G->Ad[k].indegree=0;  
        }//头结点的初始化   
        for(k=1; k<=G->e; k++)  
        {  
            printf("输入两个顶点(事件编号),边的权值(活动时间)\n");  
            cin >> j >> i >> t;  
            G->Ad[i].indegree++;  
            link* p=new link;  
            p->v=i;  
            p->weight=t;  
            p->next=G->Ad[j].firstedge;  
            G->Ad[j].firstedge=p;//在表头插入   
        }  
        printf("AOE网络构建完成\n-----人家是华丽丽的分割线-----\n打印邻接表:\n");  
        for(i=1; i<=G->n; i++)  
        {  
            cout << G->Ad[i].element;  
            link *m=G->Ad[i].firstedge;  
            while(m!=NULL)  
            {  
                printf("->%c,%d",G->Ad[m->v].element,m->weight);  
                m=m->next;  
            }  
            printf("->^\n");  
        }//邻接表打印   
        printf("\n");  
    }  
    void Criticalpath(Adgraph* G)//G为带权值的邻接表   
    {  
        queue<int> Q;  
        stack<int> S;  
        int i,j,k,count=0,ve[101],vl[101],ae,al;  
        //时间的最早发生时间和最晚发生时间,活动的最早发生时间和最晚发生时间   
        //m用来计数,判断是否有回路   
        for(i=1; i<=G->n; i++)ve[i]=0; //首先每个事件的最早发生时间都为0   
        for(i=1; i<=G->n; i++)  
            if(G->Ad[i].indegree==0) Q.push(i);  
        //将入度为0的顶点入队   
        printf("Topsort:");  
        while(!Q.empty())  
        {  
            j=Q.front();  
            Q.pop();  
            count++;  
            cout << G->Ad[j].element;  
            S.push(j);//把正序的拓扑序下标列入栈   
            link *p=G->Ad[j].firstedge;  
            while(p!=NULL)  
            {  
                k=p->v;  
                G->Ad[k].indegree--;  
                if(ve[j] + p->weight > ve[k])  
                    ve[k] = ve[j] + p->weight;  
                if(G->Ad[k].indegree==0) Q.push(k) ;  
                p=p->next;  
            }  
        }//用topsort求最早的发生时间   
        printf("\n");  
        if(count<G->n)  
        {  
            printf("有环路!\n");  
            return;  
        }  
        for(i=1; i<=G->n; i++) //为各事件v(i)的最迟发生时间vl[i]置初值   
            vl[i]=ve[G->n];  
        printf("Opp_Topsort:");  
        while(!S.empty())//按拓扑序列的逆序取顶点   
        {  
            j=S.top();  
            S.pop();//出栈   
            cout << G->Ad[j].element;  
            link *p=G->Ad[j].firstedge;  
            while(p!=NULL)  
            {  
                k=p->v;  
                if((vl[k] - p->weight)<vl[j])  
                    vl[j]=vl[k]-p->weight;  //修改vl[j]   
                p=p->next;  
            }  
        }  
        printf("\nActivity<EnventA->EnventB>      AE     AL    Share time  Is Criticalpath?:\n");  
        for(j=1; j<=G->n; j++) //扫描顶点表   
        {  
            link *p=G->Ad[j].firstedge;  
            while(p!=NULL)  
            {  
                k=p->v;  
                ae=ve[j];  
                al=vl[k]-p->weight;  
                printf("<事件%c,事件%c>\t\t\t%d\t%d\t%d    \t",G->Ad[j].element,G->Ad[k].element,ae,al,al-ae);  
                if(al==ae)//关键活动   
                    printf("Yes");  
                    else printf("No");  
                printf("\n");  
                p=p->next;  
            }  
        }  
    }  
    int main()  
    {  
        struct Adgraph G;  
        Create_AOE(&G);  
        Criticalpath(&G);  
        return 0;  
    }  
    


     

    展开全文
  • AOE网络-关键路径

    千次阅读 多人点赞 2018-10-15 18:25:32
    拓扑排序的另一个应用就是关键路径的问题,关键路径对应的是另一种网络:AOE网络。先回顾下拓扑排序中讲到的AOV网络,AOV网络即“Activity On Vertex”,即图上每一个顶点表示的是一个事件或者说一个活动,而顶点...

    拓扑排序的另一个应用就是关键路径的问题,关键路径对应的是另一种网络:AOE网络。先回顾下拓扑排序中讲到的AOV网络,AOV网络即“Activity On Vertex”,即图上每一个顶点表示的是一个事件或者说一个活动,而顶点之间的有向边则表示这两个活动发生的先后顺序。

    在关键路径这个问题中,AOE网络指的是“Activity On Edge”,即图上的每一条边表示的是一个活动,顶点作为各个“入度边事件”的汇集点,意思是,某个顶点,当所有的“入度边事件”的活动全部完成后,才开始进行该顶点的“出度边事件”。在AOE网络中只有一个入度为零的点,称作源头顶点,和一个出度为零的目的顶点。AOE网络通常用来安排一些项目的工序。

    上图表示的就是AOE网络中的,有向边上方表示该活动的持续时间,也就是完成该活动要多长时间,有向边下方表示该活动的机动时间,机动时间是什么呢,下面等拿例子来讲解时再解释。顶点里又分为三部分,一部分是存放顶点的编号,另外两部分分别存放活动的最早完成时间(即到达该点用时最短),和最晚完成时间(即到达该点用时最长)。

    下面根据一个具体的例子来看到底什么是AOE网络和关键路径:

    在下面的有向无环图中,V1是源头顶点(即开始点),到V10结束,每一条边代表一个活动,有向边的方向表示活动完成后到达哪一个汇集点。有向边上方表示的是活动完成所需要的时间(也是持续时间)。假设活动a7和a8想要开始,那么必须等到活动a4和a5都完成后,a7和a8才能开始。

    还有一种更复杂的情况是:如果活动a7和a8要开始,必须要等活动a4、a5和a6都完成后,才能开始a7和a8活动(因为在AOE网络中有些活动是可以并行地进行的)。这样的情况怎么办?我们不可以把V5和V6顶点连接起来,为什么?因为我们看a9这个活动,它的开始与否和活动a4,a5均无关系,活动a9只需等待活动a6完成他就可以开始了,所以如果我们把V5和V6顶点连接起来,是不行的。那要怎么办?方法是用一个无向虚线(标记线)把V5和V6连接,边上的权值设为0,如图:

    接着根据这个有向无环图,我们看看从开始到结束整个工程活动需要的最短时间是多少?答案是从开始点出发到完成点的最长路径的长度(这里的最长路径长度指的是路径上各个活动持续时间之和,不是指路径上边的数目)。从开始点到结束点的最长路径就叫做关键路径。从开始结点V1开始,它的最早完成时间自然是0了,然后到V2结点,V2结点的最早完成时间是5,同理V3结点最早需要4天完成,V4结点最早需要6天完成。

    接着到下一组,从V4到V6顶点,活动a6需要7天,所以V6上填上6+7=13,也就是说到达V6需要最早完成时间是13天。对于V5这个顶点,它的完成时间有三个,分别是5+3=8,4+2=6和13+0=13。这里我们就要选一个最大的填进去,因为V5的“出度边事件”要进行,也就是活动a7和a8要开始的话,必须等齐a4,a5和a6三个活动结束后才能开始,所以在a4、a5和a6中选一个完成时间最大的,就能确保三个活动都能完成。

    到这里我们就知道程序大概要怎么写了:

    首先我们需要一个Earliest[ ]数组来存放每一个顶点的最早完成时间,Earliest[ 1 ]=0代表的就是开始结点V1的最早完成时间是0,对于图中每一个顶点对<i, j>,Earliest[ j ]的值也就是j结点的最早完成时间就等于Earliest[ i ]+C<i, j>(也就是前一个结点i的最早完成时间加上i和j之间的有向边的权值),当结点j的入度边不止一条的时候,Earliest[ j ]存放的就是所有入度边中最大的值。

    按照这个思路,我们可以把图里接下来的顶点的完成时间都填好:

    到最后V10结束结点等于29,也就是说整个图的所有活动的最短完成时间是29天。

    最后到来看看这个图中活动的机动时间,什么是机动时间呢,就是指图中这些活动中,有哪些活动是一直进行下去的,没有休息时间的。例如活动a10需要3天完成,而获得a11需要2天,则a11有1天的休息时间等待a10完成,a11的这一天休息时间就是所谓的“机动时间”。

    我们用e(i)来表示活动ai的最早完成时间,l(i)表示ai的最迟开始时间,机动时间要怎么算呢?看图来说,我们从结束结点开始倒推,在保证整个工期都不推迟的情况下,也就是第29天开始,反推回去,看结点V9,活动a12需要5天,就是说在保证整个工期能在29天完成的情况下,V9的最晚开始时间(也就是最迟完成时间)是29-5=24,就是说活动a12最迟必须在第24天就要开始工作了。V7结点和V8结点同理,V7结点最迟必须在第24-3=21天就开始工作,V8结点最迟必须在第24-2=22天开始就工作。

    接着看V5结点,从V8倒推到V5,就是22-7=15,a8活动最迟第15天就要开始工作。而从V7倒推到V5的话,21-8=13,a8活动最迟第13天就要开始工作,这里出现两个不同的值,怎么选?答案是选最小值13,因为如果选择第15天开工,那么对于活动a7来说,就延迟了两天开工了,这样就不能保证后面能在29天内完成整个工程,所以遇到两种不同的最晚开始时间时,我们要选最小的,这样才能保证整个工期不被延误。

    同样的,看V6结点,从V8结点倒推到V6结点,22-5=17天,也就是活动a9的最迟开始时间可以是在第17天时才开工?答案是不行的,因为V6结点和V5结点有个虚线连着呢,V6结点,也就是活动a9的最迟开始时间同样是13天。

    从这里就可以看出我们的求机动时间的倒推时的推断是,需要一个Latest[ ]数组存放每一个结点的最迟开始时间,一开始初始化结束结点的Latest[ 10 ]=Earliest[ 1 ],也就是29。然后倒推时,Latest[ i ]就等于Last[ j ]-C<i, j>.。如果某个结点有多个出度边,那么就选择最小值赋给Last[ i ]就可以了。

    按照这个推断,就可以把剩下的顶点的最晚开始时间都算出来:

    V1顶点有三种选择,V2到V1等于5,V3到V1等于7,V4到V1等于0,因为我们要选择最小值,所以V1填上0。

    最后来看看每个结点的机动时间,我们从头开始看,活动a1需要工作5天才完成,到达V2结点中,最迟开始时间是10,也就是说活动a4最迟在第10天开始工作都不会耽误整个工期,而a1从第0天开始只需工作5天就能完成,所以活动a1的机动时间就是10-0-5=5,五天。活动a2最迟在第11天开始工作就可以了,而活动a2只需要4天就可以完成,所以a2的机动时间是11-0-4=7,七天。活动a3等于6-0-6=0,所以活动a3机动时间等于0,也就是说活动a3完成后就要开始下一个活动了,中间没有“休息时间”。

    同理可看出,a4的机动时间是13-5-3=5。a5的机动时间是13-4-2=9。a6是13-6-7=0。这样我们就可以把所有的机动时间都算出来:

    我们假设用e(i)表示活动ai的最早开始时间,用l(i)表示活动的最迟开始时间,那么两者之差l(i)-e(i)表示活动ai的机动时间,把e(i)=l(i)的活动我们称为“关键活动”。关键路径上所有的活动都是关键活动。回到关键路径的问题,关键路径有可能不止一条。所以找出关键路径即找出路径上所有活动都是关键活动的路径即可。

    /*拓扑排序*/
    bool TopSort(ListGraphNode MyGraph, Vertex TopOrder[]) 
    {
    	/*TopOrder[]数组用来顺序存储排序后的顶点的下标*/
    	/*在拓扑排序完成后直接顺序输出TopOrder[]里的元*/
    	/*素就能得到拓扑排序序列*/ 
    	int i;
    	int Indegree[MaxVertex], cnt;/*Indegree数组是图中顶点的入度,cnt是计数器*/
    	Vertex V;/*扫描V顶点的邻接点*/
    	PtrlPointNode W; /*邻接表方式表示图*/
    	Queue PtrQ=Start();
    	for (i=0; i<MaxVertex; i++) {
    		PtrQ->Data[i]=-1;
    	}
    	
    	/*初始化入度数组*/
    	for (V=0; V<MyGraph->numv; V++) {
    		Indegree[V]=0;
    	}
    	
    	/*遍历图,得到图中入各顶点的入度情况并存入Indegree数组中*/
    	for (V=0; V<MyGraph->numv; V++) {
    		for (W=MyGraph->PL[V].HeadEdge; W; W=W->Next) {
    			Indegree[W->Tail]++;
    		}
    	}
    	
    	/*将所有入度为0的顶点入列*/
    	for (V=0; V<MyGraph->numv; V++) {
    		if (Indegree[V]==0) {
    			Push(PtrQ, V);
    		}
    	}
    	
    	/*开始拓扑排序*/
    	cnt=0; /*初始化计数器为0*/
    	while (PtrQ->End!=PtrQ->Head) {
    		V=Delete(PtrQ);/*出列一个入度为0的顶点*/
    		TopOrder[cnt++]=V;/*拓扑排序数组里记录该出列顶点的下标*/
    		/*遍历对于V的每个邻接点W->PL.HeadEdge.index*/ 
    		for (W=MyGraph->PL[V].HeadEdge; W; W=W->Next) {
    			/*若删除V能使该顶点的入度为0*/
    			if (--Indegree[W->Tail]==0) {
    				/*把该顶点入列*/
    				Push(PtrQ, W->Tail);
    			}
    			/*同时更新Earliest数组的值*/
    			if ((Earliest[V]+W->Weight)>Earliest[W->Head]) {
    				Earliest[W->Tail]=Earliest[V]+W->Weight;
    			} 
    		}
    	}
    	/*最后判断*/
    	if (cnt!=MyGraph->numv) {
    		return false;/*说明该图里有回路,返回false*/
    	} else {
    		return true;
    	}
    }

    在拓扑排序过程中,我们就同时更新Earliest数组,把每一个顶点的最早完成时间填入到数组中。

    /*关键路径*/
    bool CriticalPath(ListGraphNode MyGraph, int TopOrder[])
    {
    	int k, ee, el;
    	PtrlPointNode W;
    	Queue List=Start();
    	/*得到后面逆序用*/
    
    	for (k=0; k<MyGraph->numv ; k++) {
    		Push(List, TopOrder[k]); 
    	} 
    
    	/*初始化Lastest数组*/ 
    	for (k=0; k<MyGraph->numv; k++) {
    		Lastest[k]=Earliest[MyGraph->numv-1];
    	}
    	
    	/*开始关键路径*/
    	while (List->End!=List->Head) {
    		k=Delete(List);/*出列一个入度为0的顶点*/
    		/*遍历对于V的每个邻接点W->PL.HeadEdge.index*/ 
    		for (W=MyGraph->PL[k].HeadEdge; W; W=W->Next) {
    		if (Lastest[k]>(Lastest[W->Tail]-W->Weight)) {
    			Lastest[k]=Lastest[W->Tail]-W->Weight;
    		}	
    	}
    	
    	//printf("关键路径为:"); 
    	for (k=0; k<MyGraph->numv; k++) {
    		W=MyGraph->PL[k].HeadEdge;
    		while (W) {
    			ee=Earliest[k];
    			el=Lastest[W->Tail]-W->Weight;
    			if (ee==el) {
    				/*两值相等说明它们是关键活动*/
    				printf("v%d--v%d=%d", MyGraph->PL[k].HeadEdge->Tail, MyGraph->PL[W->Head].HeadEdge->Tail, W->Weight);
    				}
    				W=W->Next;
    			} 
    		}
    	}
    }

    在关键路径的计算过程中再逆序计算出最迟开始时间即可。

    完整代码在个人代码云:

    https://gitee.com/justinzeng/codes/9jbqdrhgn8xl31y6vsw2u75

    展开全文
  • 有良好界面的JAVA编写的AOE网络求取关键路径,比较完善
  • AOE网络关键路径问题

    千次阅读 2017-06-04 12:01:31
    寻找AOE网络关键路径目的是:发现该活动网络中能够缩短工程时长的活动,缩短这些活动的时长,就可以缩短整个工程的时长。因此,寻找关键路径就是寻找关键活动。接下来开始寻找一个工程中的关键路径(关键活动)。...

    关于AOE网络的基本概念可以参考《数据结构》或者search一下就能找到,这里不做赘述。

    寻找AOE网络的关键路径目的是:发现该活动网络中能够缩短工程时长的活动,缩短这些活动的时长,就可以缩短整个工程的时长。因此,寻找关键路径就是寻找关键活动

    接下来开始寻找一个工程中的关键路径(关键活动)。

    寻找关键路径,每本教材都会提及四个特征属性:Ve[],Vl[],e[],l[],此处可能还补充一个属性:活动ai的时间余量,也就是l[i]-e[i],当某个活动的时间余量=0时,该活动就是关键活动。所以,寻找关键路径(关键活动)也就是求解AOE网络中所有活动、事件的上述特征属性,然后发现时间余量为零的活动,这样的活动就是关键活动

    至此,我们分析出,求解四个特征属性就可以找到关键路径。


    1. Ve[i]:事件Vi的最早可能发生时间。
      按照就是以起始事件为源点,类似于迪杰斯特拉算法求解单源点的最长路径

    2. Vl[i]:事件Vi的最迟允许发生时间。
      结束事件的最迟允许发生时间=最早可能发生时间,以此为基础,按照拓扑序列求解前驱事件的Vl[],每次减去关联两个事件的具有最短时长的活动。

    3. e[i]:活动ai的最早可能开始时间。
      若活动ai由弧<.vk,vj>表示,则活动ai的最早开始时间应该等于事件vk的最早发生时间Ve[k]。因而,有:e[i]=ve[k];(即:边(活动)的最早开始时间等于,它的发出顶点的最早发生时间)。

    4. l[i]:活动ai的最迟允许开始时间。
      若活动ai由弧<.vk,vj>表示,则ai的最晚开始时间要保证事件vj的最迟发生时间不拖后。 因而有:l[i]=Vl[j]-dur<.vk,vj>(为边(活动)的到达顶点的最晚发生时间减去边的权值)。

    至此,所有计算完成,如果活动ai的e[i]=l[i],则ai是关键活动。

    注意,如果某项工程中,多个关键活动构成了两条或更多关键路径,此时并不是缩短任意关键活动的时间都能缩短整个工程时间,而是要缩短所有关键路径的公共关键活动的时间

    例子或者详细概念,可以参考这篇博文:
    http://blog.csdn.net/wang379275614/article/details/13990163

    展开全文
  • AOE关键路径

    2015-12-15 11:51:17
    教你轻松计算AOE关键路径 认识AOE网 有向图中,用顶点表示活动,用有向边表示活动之间开始的先后顺序,则称这种有向图为AOV网络;AOV网络可以反应任务完成的先后顺序(拓扑排序)。 在AOV网的边上加上...
    
    滴水穿石

    教你轻松计算AOE网关键路径


    认识AOE网

    有向图中,用顶点表示活动,用有向边表示活动之间开始的先后顺序,则称这种有向图为AOV网络;AOV网络可以反应任务完成的先后顺序(拓扑排序)。

    在AOV网的边上加上权值表示完成该活动所需的时间,则称这样的AOV网为AOE网,如下图:



     

    图中,顶点表示事件(能被触发,两特征属性:最早发生时间Ve(j);最晚发生时间Vl(j)),边表示活动(能被开始,两特征属性:最早开始时间e(i);最晚开始时间l(i)),权表示活动持续时间,通常用AOE网来估算工程完成的时间


    两条原则:

    Ø  只有某顶点所代表的事件发生后,从该顶点出发的各活动才能开始

    Ø  只有进入某顶点的各活动都结束,该顶点所代表的事件才能发生


    计算关键路径

    首先,在AOE网中,从始点到终点具有最大路径长度(该路径上的各个活动所持续的时间之和)的路径为关键路径。

    计算关键路径,只需求出上面的四个特征属性,然后取e(i)=l(i)的边即为关键路径上的边(关键路径可能不止一条)。

    先来看看四个特征属性的含义:

    Ø Ve(j):是指从始点开始到顶点Vk的最大路径长度


    计算技巧:

    (1)从前向后,取大值:直接前驱结点的Ve(j)+到达边(指向顶点的边)的权值,有多个值的取较大者

    (2)首结点Ve(j)已知,为0


    如上图各顶点(事件)的Ve(j): (从V1开始)



     

    Ø  Vl(j):在不推迟整个工期的前提下,事件vk允许的最晚发生时间


    计算技巧:

    (1)从后向前,取小值:直接后继结点的Vl(j) –发出边(从顶点发出的边)的权值,有多个值的取较小者;

    (2)终结点Vl(j)已知,等于它的Ve(j)


    如上图各顶点(事件)的Vl(j): (从V7开始,它的最早、最晚发生时间相同,都为10):



     

    Ø  e(i): 若活动ai由弧<vk,vj>表示,则活动ai的最早开始时间应该等于事件vk的最早发生时间。因而,有:e[i]=ve[k];(即:边(活动)的最早开始时间等于,它的发出顶点的最早发生时间

    如上图各边(活动)的e(i):



     

    Ø  l(i): 若活动ai由弧<vk,vj>表示,则ai的最晚开始时间要保证事件vj的最迟发生时间不拖后。 因而有:l[i]=vl[j]-len<vk,vj>1(为边(活动)的到达顶点的最晚发生时间减去边的权值

    如上图各边(活动)的l(i):



     

    至此已介绍完了四个特征属性的求法,也求出了上图中边的e(i)和l(i),取出e(i)=l(i)的边为a1、a2、a4、a8、a9,即为关键路径上的边,所以关键路径有两条:a1 a4 a9和 a2 a8 a9



     

    总结

    求关键路径,只需理解顶点(事件)和边(活动)各自的两个特征属性以及求法即可:

    Ø  先根据首结点的Ve(j)=0由前向后计算各顶点的最早发生时间

    Ø  再根据终结点的Vl(j)等于它的Ve(j)由后向前依次求解各顶点的最晚发生时间

    Ø  根据边的e(i)等于它的发出顶点的Ve(j)计算各边的最早开始时间(最早开始,对应最早发生)

    Ø  根据边的l(i)等于它的到达顶点的Vl(j)减去边的权值计算各边的最晚开始时间(最晚开始,对应最晚发生)

    展开全文
  • AOE网络关键路径(二)——实现

    千次阅读 2014-04-07 11:43:50
    这一篇来实现下AOE网络关键路径~
  • AOE网络关键路径(一)

    千次阅读 2014-04-07 00:24:12
    1、与AOV网络密切相关的是AOE网络。如果在DAG中用有向边表示一个工程的各项活动,用有向边上的权值表示活动的持续时间,用顶点表示事件,则这种有向图叫做用边表示活动的网络(Activity On Edge),简称AOE网络; ...
  • 活动网络——AOE网络

    2017-02-16 17:42:45
    AOE网络 关键路径
  • AOE网络关键路径

    千次阅读 2018-08-25 23:00:20
    更加具体的知识点请取中国大学MOOC搜索浙大版数据结构,这里只给出了代码的实现。这个算法我没有找到比较好的实现,所以自己实现的有些复杂... AOE: 在现代化管理中,人们常用有向图来描述和分析一项工程的计划和...
  • 教你轻松计算AOE关键路径

    万次阅读 多人点赞 2018-09-19 16:14:23
    转:教你轻松计算AOE关键路径 认识AOE网  有向图中,用顶点表示活动,用有向边表示活动之间开始的先后顺序,则称这种有向图为AOV网络;AOV网络可以反应任务完成的先后顺序(拓扑排序)。  在AOV网的边上加上...
  • AOE关键路径求解例题 三道 首先明确顶点是事件,边是活动。 1 2 3 解题技巧: 先求Ve 从前往后推,取活动之和最大的 作为顶点(事件)最早发生时间; 求Vl 通过Ve知道最后汇点的最晚发生时间(和汇点的最...
  • 上一篇的拓扑排序中提到了 AOV\mathrm{AOV}AOV 网(Activity On Vertex Network),与之相对应的是 AOE\mathrm{AOE}AOE 网(Activity on edge network),即边表示活动的网。 AOV\mathrm{AOV}AOV 用顶点表示活动的网...
  • 认识AOE网  有向图中,用顶点表示活动,用有向边表示活动之间开始的先后顺序,则称这种有向图为AOV网络;AOV网络可以反应任务完成的先后顺序(拓扑排序)。  在AOV网的边上加上权值表示完成该活动所需的时间,则...
  • 【笔记】AOE网与关键路径

    万次阅读 多人点赞 2017-12-02 01:06:32
    AOE关键路径关键路径的算法实现
  • //求AOE网络中的关键路径算法 #include <cstdio> #include <cstring> #define MAXN 100 //顶点个数的最大值 #define MAXM 200 //边数的最大值 struct ArcNode { int to, dur, no; //边的另一个顶点持续时间活动序号 ...
  • ve(i)=a1到ai的最长路径 2.求每个事件–顶点i的最迟发生时间 vl(i)=每个顶点i的所有的*出边所对应的顶点k的ve(k)减去这个顶点k对应的出边的路径长度*的最小值 3.每个活动(边i)的最早开始时间 e(i)=这条边的箭尾对应...
  • 认识AOE网  有向图中,用顶点表示活动,用有向边表示活动之间开始的先后顺序,则称这种有向图为AOV网络;AOV网络可以反应任务完成的先后顺序(拓扑排序)。  在AOV网的边上加上权值表示完成该活动所需的时间,则称...
  • 找代码废了很大的时间,有些代码存在问题,...#裘宗燕数据结构中的aoe网络代码"""topological sort of direct graph """class Graph: #basic graph class, using adjacent matrix ...
  • 1.计算每个活动的最早发生时间(正序) earliest[1]=0; earlest[k]=max{earliest[j],+dut[j][k]} 2.计算每个活动的最晚发生时间(逆序) lastest[n]=earliest[n];...lastest[j]=min{listest[k]-dut[j][k]}...将关键...
  • 本次结合系统分析师—运筹方法—网络规划技术—关键路径章节,对原文链接描述不准确的地方做了修正。 认识AOE网  有向图中,用顶点表示活动,用有向边表示活动之间开始的先后顺序,则称这种有向图为AOV...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,071
精华内容 428
关键字:

aoe网络的关键路径