AOE网的关键路径

引入

生活中往往有着这样的场景,我们想做一件事情,但是需要做其他的事情来达到这件事情,例如,学数据结构之前,首先需要学一门程序设计语言,还要学习离散数学,如果学语言需要耗费半年时间,学离散数学需要一年事件,那么我们能学数据结构需要的最短时间是一年

  • 但是,这样的场景往往出现在工程项目中,往往有许许多多的事件和活动,我们需要做的是找到能够影响整个工程进行时间的那一条路径,这个过程类似于木桶原理,这条路径应该是最长的那一条,这样他进行的时间就决定了工程的时间,这样一条路径就是这个工程网络的关键路径
  • 我们需要获取这样一条路径来告诉项目经理应该着重关心哪些事件
  • 我们也可以利用它去估算工程的完成时间

AOE网的判断

  • 什么叫AOE网
    AOE网(average of edge),也就是用边去表示活动的网,它是一种带权的有向无环图,其中,顶点表示事件,弧表示活动,权表示活动持续的时间
  • 要想说明一个网络是否是AOE网,最重要的是判断是否有环,因为如果出现环,就说明一个事件以自己为先决条件,这是荒谬的
  • 判断图中是否出现环,最常规的方法是采用拓扑排序

拓扑排序

  • 这个排序的过程是简单的,首先要找到一个无前驱的点,这就是拓扑序列的第一个点
  • 接着,从图中删除此点和以它为尾的弧
  • 巩固一下知识点,如果<x,y>表示从顶点x到y的一条弧,那么x叫做弧尾或起始点,y叫做弧头或终端点
  • 重复刚才的步骤,直至图中不存在无前驱的点,这个时候看图中是否还剩下点,如果还有,说明图中有环;否则,找到的这些点就构成了这个图的拓扑序列,图中无环
template<class TypeOfVer,class TypeOfEdge>
bool adjlist_graph<TypeOfVer,TypeOfEdge>::TopSort(){
    if(GraphKind == "UDG"||GraphKind =="UDN") return false;
    queue<TypeOfEdge> q;
    int inDegree[Vers];
    int vis[Vers];
    int topsort[Vers];
    for(int i=0;i<Vers;i++){
        int f = Get_InDegree(i);
        if(f == -1) inDegree[i] = 0;
        else inDegree[i] = f;
        vis[i] = 0;
        if(inDegree[i] == 0) q.push(i);
    }
    edgeNode<TypeOfEdge> *p;
    int num = 0;
    while(!q.empty()){
        int x = q.front();
        q.pop();
        vis[x] = 1;
        topsort[num] = x;
        num++;
        p = verList[x].head;
        while(p){
            if(inDegree[p->data]) inDegree[p->data]--;
            if(!vis[p->data]&&inDegree[p->data] == 0) q.push(p->data);
            p = p->next;
        }
    }
    // for(int i=0;i<num;i++){
    //     if(i) cout<<"->";
    //     cout<<verList[topsort[i]].ver;
    //     if(i == num-1) cout<<endl;
    // }
    if(num == Vers) return true;
    return false;
}

相关函数参见邻接表ADT

事件的最早发生时间和最晚发生时间

在这里插入图片描述
如上图,所有的a即表示活动,所有的v表示事件

  • 我们使用两个数组,ve[]表示事件的最早发生时间,vl[]表示事件的最晚发生时间
  • 事件v0显然最早发生时间为0,那么事件v1需要在v0发生以后才能发生,所以最早发生时间应该为6,v2、v3与之相同,那么v4呢,它取决于v1和v2的完成时间,必须他们都完成v4才能够开始,所以v4的最早发生时间应该为更大的7,到这里我们就可以知道该怎么做了,直接利用前一个活动递推下一个活动时间,需要注意的是最早发生时间应该取较大的时间
  • 那么最晚发生时间呢?何为最晚,应该是说它的完成时间不应该影响到后一个事件的完成时间,也就是确保工程能完成那么显然应该从后往前看,并且最后一个最晚发生时间应该与其最早发生时间相同,我们继续算一下,首先v8最晚发生时间为18,求v6、v7都是容易的,那么v4呢?因为它是从两条路径过来的,为了不拖延它之后的两个事件,那么我们应该取较小的那一个时间,因为注意这都是最晚完成时间,如果你取大的,小的那一个事件就完不成,那么最终事件就不能完成,仔细想一下就可以明白
    for(int i=0;i<Vers;i++) ve[i] = 0;
    for(int i=0;i<Vers;i++){
        int k = topSort[i];
        edgeNode<int> *p = verList[k].head;
        while(p){
            int j = p->data;
            if(ve[j]<ve[k]+p->weight){
                ve[j] = ve[k]+p->weight;
            }
            p=p->next;
        }
    }for(int i=0;i<Vers;i++) vl[i] = ve[Vers-1];
    for(int i=Vers-1;i>=0;i--){
        int k = topSort[i];
        edgeNode<int> *p = verList[k].head;
        while(p){
            int j = p->data;
            if(vl[k]>vl[j]-p->weight) vl[k] = vl[j]-p->weight;
            p=p->next;
        }
    }

活动的最早开始时间和最晚开始时间

  • 首先活动怎么表示?应该用<x,y>也就是一条弧,那么最早开始时间显然应该是事件x的最早发生时间,最晚发生时间应该是y的最晚发生时间再去掉边权,因为是开始的时间
    for(int i=0;i<Vers;i++){
        edgeNode<int> *p = verList[i].head;
        while(p){
            int j = p->data;
            int e = ve[i];
            int l = vl[j]-p->weight;
            cout<<'<'<<verList[i].ver<<','<<verList[j].ver<<'>'<<'\t'<<ve[i]<<'\t'<<l<<endl;
            p=p->next;
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Clarence Liu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值