zoukankan      html  css  js  c++  java
  • 拓扑排序和关键路径

    1. 拓扑排序

      不存在有向环路的有向图称为无环路有向图。无环有向图可用于表示偏序集。设R是有穷集合X上的偏序关系,对X的每个v,用一个以v为标号的顶点表示,由此构成顶点集V。对R中任意一个序对(a,b),a不等于b,由对应的两个顶点建立一条边(a,b),由此构成边集E,则G=(V,E)是无环路有向图。

      下面介绍由广度优先搜索算法演变而得到的拓扑排序算法。

      给定一个无环路有向图G=(V,E),各顶点的编号为V={1,2,...,n}。要求用label[i]对每个顶点i重新进行编号,使得若i是j的前导顶点(广度优先搜索),则label[i] < label[j]。即拓扑排序是将无环路有向图的每个顶点排成一个线性序列,使得当从顶点i到顶点j存在一条边时,则在线性序列中,将i排在j的前面。

    代码如下:

        //输入为邻接表
        void TopoOrder(GRAPH L)
        {
            QUEUE Q;
            vertex v,w;
            int nodecount;
            MakeNull(Q);
            //入度为0的顶点进队
            for(v=1;v<=n;v++)
                if(indegree[v]=0)
                    EnQueue(v,Q);
                nodecount = 0;
            while(!Empty(Q)) {
                v = Front(Q);
                DeQueue(Q);
                count << v;
                nodecount ++;
                for(邻接于v的每个顶点w) {
                    indegree[w] = indegree[w] - 1;//删除由v发出的边
                    if(indegree[w] == 0)
                        EnQueue(w,Q);
                }
            }
            if(nodecount < n)
                cout << "you huan lu a!";
        }
    

    2. 关键路径

    2.1 概念

      在引进“关键路径”这个词之前,先介绍一下与它密不可分的几个概念。如果在带权的有向图中,用顶点表示事件,边表示活动,权表示活动持续的时间。把这样的有向图称为关于边的活动网。与之相对应,若用顶点表示活动,用边表示活动的先后顺序关系,这样的有向图称为关于顶点的活动网,例如拓扑图。将这些活动网统称为AOE网

    image_1be7ohfpdum21jihd81h9gbt39.png-22.3kB

      事件v5表示活动a4和a5已结结束,a7和a8可以开始。边上的数字为持续的时间。

      显然,在AOE网中,由于有些活动可以同时进行,所以完成工程最小时间是从起始点到结束点最长路径的长度,把从起始点到结束点具有最大长度的路径称为关键路径。图中的a1-a4-a7-a10(长为18)就是其中一条关键路径。关键路径的长度代表完成这个工程最少需要的时间。这里需要注意,活动的时间只是指完成该活动的最少时间,实际上可能会拖延什么的。

      从AOE网的起始点v1到其中某一顶点vi的最长路径的长度,称为事件vi的最早发生时间,记为VE[i]。如事件v5的最早发生时间为7。

      用E(i)表示活动ai的最早开始时间。事件vi的最早发生时间决定了以vi为起点的所有边上的活动的最早开始时间。如E(7)=E(8)=事件v5的最早发生时间=7。

      对于活动ai,还定义一个最迟开始时间,它是不使整个工程的完成时间拖延的最晚开始时间。用L(i)表示。如,L(6)=18-a11-a9-a6=8。

      对于事件vi,也有一个最迟发生时间VL[i]。

    关键路径上,所有活动都满足E(i) = L(i),把满足这一等式的所有活动称为关键活动

      活动ai的最迟开始时间和最早开始时间之差表示ai的完成时间余量,即允许ai延缓的时间。

    2.2 寻找关键活动

      求解关键活动在于求解E(i)和L(i)。

      设活动ai所对应的边为(k,m),并且用ACT[k][m]来表示一个活动的持续时间,很明显:
        E(i) = VE[k] 或者用E(k,m)
        L(i) = VL[m] - ACT[k][m] 或者用L(k,m)

    现在就转化为求解VE[i]和VL[i],分成两步:

    • 前进阶段:从VE1=0开始,沿着路径上每条边的方向,应用如下公式求出每个事件的最早发生时间:
          VE[m] = max{VE[k]+ACT[k][m]},k是m的直接前导顶点
    • 回退阶段:从已求出的VL[n]=VE[n]开始,沿着路径上每条边的相反方向,应用如下公式:
          VL[k] = min{VL[m]-ACT[k][m]},m为k的直接后续顶点

    可以用类似拓扑排序的算法求出L[i]和E[i],对于这两者都相等的活动则是关键活动,将所有非关键活动删除后得到的图,任意一条路径都是关键路径。

  • 相关阅读:
    利用Java API通过路径过滤上传多文件至HDFS
    docker-compose部署haproxy
    PM2 常用命令
    shell脚本循环访问url直到状态码返回200跳出循环
    CentOS 7.6安装配置Chrony同步系统时钟
    PostgreSQL9.5数据库锁表问题分析与解决
    linux系统netstat命令详解(netstat常用运维命令)
    linux目录备份脚本
    PostgreSQL 锁等待监控 珍藏级SQL
    docker部署pgadmin4并通过nginx反向代理
  • 原文地址:https://www.cnblogs.com/vachester/p/6743975.html
Copyright © 2011-2022 走看看