AOV网(拓扑排序)和AOE网

目录

AOV网(Activity On Vertex Network)

拓扑排序(Topological Sort)

拓扑排序 – 思路

拓扑排序 – 实现

AOE网 (Activity On Edge Network)

AOV网与AOE网的关系

拓扑排序应用

LeetCode_210:课程表


AOV(Activity On Vertex Network)

一项大的工程常被分为多个小的子工程, 子工程之间可能存在一定的先后顺序,即某些子工程必须在其他的一些子工程完成后才能开始; 在现代化管理中,人们常用有向图来描述和分析一项工程的计划和实施过程,子工程被称为活动(Activity)

顶点表示活动、有向边表示活动之间的先后关系,这样的图简称为 AOV 网, 标准的AOV网必须是一个有向无环图(Directed Acyclic Graph,简称 DAG)

拓扑排序(Topological Sort)

前驱活动:有向边起点的活动称为终点的前驱活动  (注意: 只有当一个活动的前驱全部都完成后,这个活动才能进行)
后继活动:有向边终点的活动称为起点的后继活动


什么是拓扑排序?
将 AOV 网中所有活动排成一个序列,使得每个活动的前驱活动都排在该活动的前面
比如上图的拓扑排序结果是:A、B、C、D、E、F 或者 A、B、D、C、E、F (结果并不一定是唯一的)

拓扑排 思路

可以使用卡恩算法(Kahn)完成拓扑排序
假设 L 是存放拓扑排序结果的列表
(1) 把所有入度为 0 的顶点放入 L 中,然后把这些顶点从图中去掉
(2) 重复操作(1),直到找不到入度为 0 的顶点
     如果此时 L 中的元素个数和顶点总数相同,说明拓扑排序完成
     如果此时 L 中的元素个数少于顶点总数,说明原图中存在环,无法进行拓扑排序

拓扑排 实现

在代码实现中, 使用一个map来维护顶点与该顶点入度的关系, 当某个顶点的入度为 0 , 那么该顶点需要放入list列表中, 进行排序, 并将该顶点所属边的终点顶点的入度 -1, 模拟移除该顶点; 

/**
 * 拓扑排序(卡恩算法)
 */
@Override
public List<V> topologicalSort() {
    List<V> list = new ArrayList<>(); //存储排好序的顶点值
    Queue<Vertex<V, E>> queue = new LinkedList<>(); //存储度为0的顶点
    Map<Vertex<V, E>, Integer> ins = new HashMap<>(); //存储顶点与实时入度的映射

    /**
     * 将入度为 0的顶点入栈,作为起始顶点;
     * 将入度不为 0的顶点加入ins映射中, 后面进行实时更新
     */
    vertices.forEach((V v,Vertex<V,E> vertiex)->{
        int inSize = vertiex.inEdges.size();
        if(inSize == 0){
            queue.offer(vertiex);
        }else{
            ins.put(vertiex,inSize);
        }
    });

    while(!queue.isEmpty()){
        Vertex<V, E> vertex = queue.poll(); //队头元素出队
        list.add(vertex.value);  //加入集合

        /**
         * 模拟vertex顶点删除, 该顶点所有的边的to顶点的入度需要-1
         */
        vertex.outEdges.forEach((Edge<V,E> edge)->{
            int inSize = ins.get(edge.to) - 1;
            if(inSize == 0){
                queue.offer(edge.to);
            }else{
                ins.put(edge.to,inSize);
            }
        });
    }

    return list;
}

AOE网 (Activity On Edge Network)

AOE网的定义:在带权有向图中若以顶点表示事件,有向边表示活动,边上的权值表示该活动持续的时间,这样的图简称为AOE网

这里写图片描述

如上所示,共有11项活动(11条边), 9个事件(9个顶点)。整个工程只有一个开始点和一个完成点。即只有一个入度为零的点 (源点) 和只有一个出度为零的点(汇点)
关键路径:是从开始点到完成点的最长路径的长度。路径的长度是边上活动耗费的时间
如上图所示,1 -> 2 -> 5 -> 7 -> 9是关键路径(关键路径不止一条,请输出字典序最小的), 权值的和为18

AOV网与AOE网的关系

从定义上来看,很容易看出两种网的不同,AOV网的活动以顶点表示,而AOE网的活动以有向边来表示,AOV网的有向边仅仅表示活动的先后次序。纵观这两种网图,其实它们总体网络结构是一样的,仅仅是活动所表示的方式不同,因此可以猜想从AOV网转换成AOE网应该是可行的。

  通常AOE网都是和关键路径联系在一起的,在AOE网中我们可以通过关键路径法来计算影响整个工期的关键路径,达到缩短工期的目的。在传统的AOV网中是没有表示活动时间的权值的,因此传统的AOV网无法估算工期,但是如果我们在AOV网中的活动结点上都标上时间属性,那么AOV网就可以完全转换为AOE网。

拓扑排序应用

LeetCode_210:课程表

  • 4
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
拓扑排序是一种常用的有向无环图(DAG)的排序算法,其主要思想是将有向图中的节点按照一定的顺序进行排序,使得所有的有向边从排在前面的节点指向排在后面的节点。在AOV中,节点代表活动,有向边代表活动之间的先后关系。 以下是一个使用C语言实现拓扑排序的示例代码: ```c #include <stdio.h> #define MAXVEX 100 //节点最大数目 int main() { int i, j, k, n, e; int flag[MAXVEX]; int in[MAXVEX]; int topo[MAXVEX]; int arc[MAXVEX][MAXVEX]; //邻接矩阵 //输入节点数和边数 printf("请输入节点数和边数:"); scanf("%d%d", &n, &e); //初始化邻接矩阵和入度数组 for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { arc[i][j] = 0; } in[i] = 0; flag[i] = 0; } //输入每条有向边的起始节点和结束节点 for (k = 0; k < e; k++) { printf("请输入第%d条有向边的起始节点和结束节点:", k + 1); scanf("%d%d", &i, &j); arc[i][j] = 1; in[j]++; } //拓扑排序 for (i = 0; i < n; i++) { if (in[i] == 0) { flag[i] = 1; topo[0] = i; break; } } for (i = 1; i < n; i++) { for (j = 0; j < n; j++) { if (flag[j] == 0 && in[j] == 0) { flag[j] = 1; topo[i] = j; for (k = 0; k < n; k++) { if (arc[j][k] == 1) { in[k]--; } } break; } } } //输出拓扑排序结果 printf("拓扑排序结果为:"); for (i = 0; i < n; i++) { printf("%d ", topo[i]); } printf("\n"); return 0; } ``` 在该代码中,使用邻接矩阵来表示有向图,使用入度数组来表示每个节点的入度。在拓扑排序过程中,依次遍历每个节点,如果该节点的入度为0,则将其加入到拓扑序列中,并将其后继节点的入度减1。重复这个过程直到所有节点都被遍历过。最终得到的拓扑序列就是一种满足所有先后关系的顺序。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值