【数据结构】图-----关键路径

一、核心前提

  1. AOE 网 :有向无环、带权边,边代表活动,顶点代表事件;源点(起点:入度为 0)、汇点(终点:出度为 0)。
  2. 关键路径 :从源点 → 汇点 的最长路径 ;决定工程最短完成时间 ,路径上活动为关键活动。

二、四大必背参数(考试核心)

设:顶点为事件,边为活动

  1. vei :事件 i 的最早发生时间
  2. vli :事件 i 的最晚发生时间
  3. e :活动最早开始时间
  4. l :活动最晚开始时间 l−e=0 → 该活动为关键活动

计算公式

  1. 最早发生时间(正向拓扑)源点权

  2. 最晚发生时间(逆拓扑)汇点汇点权

  3. 活动时间

  • 活动 <u,v>:e=veu,l=vlv−w

三、算法步骤

  1. 对 AOE 网做拓扑排序
  2. 按拓扑序正向遍历,求数组 ve
  3. 按逆拓扑序反向遍历,求数组 vl
  4. 遍历所有边,计算 、
  5. l−e=0 的边 → 关键活动,串联即为关键路径

四、完整 C 语言代码(邻接表・带详细注释)

复制代码
#include <stdio.h>
#include <string.h>
#define MAXN 105
#define INF 0x3f3f3f3f

// 边结点:终点、权值、后继边
typedef struct Edge{
    int to,w;
    struct Edge *next;
}Edge;

Edge* G[MAXN];
int n,m;
int in[MAXN];        // 入度
int topo[MAXN],cnt;  // 拓扑序列
int ve[MAXN],vl[MAXN];

// 加边
void addEdge(int u,int v,int w){
    Edge *p=(Edge*)malloc(sizeof(Edge));
    p->to=v; p->w=w; p->next=G[u];
    G[u]=p;
    in[v]++;
}

// 1.拓扑排序,得到topo数组
void TopSort(){
    int stk[MAXN],top=0;
    cnt=0;
    for(int i=1;i<=n;i++)
        if(in[i]==0) stk[top++]=i;

    while(top>0){
        int u=stk[--top];
        topo[++cnt]=u;
        for(Edge *p=G[u];p;p=p->next){
            int v=p->to;
            in[v]--;
            if(in[v]==0) stk[top++]=v;
        }
    }
}

// 2.求ve:正向拓扑
void getVE(){
    memset(ve,0,sizeof(ve));
    for(int i=1;i<=cnt;i++){
        int u=topo[i];
        for(Edge *p=G[u];p;p=p->next){
            int v=p->to;
            if(ve[v] < ve[u]+p->w)
                ve[v] = ve[u]+p->w;
        }
    }
}

// 3.求vl:逆拓扑
void getVL(){
    for(int i=1;i<=n;i++) vl[i]=ve[topo[cnt]];
    for(int i=cnt;i>=1;i--){
        int u=topo[i];
        for(Edge *p=G[u];p;p=p->next){
            int v=p->to;
            if(vl[u] > vl[v]-p->w)
                vl[u] = vl[v]-p->w;
        }
    }
}

// 4.查找并输出关键活动、关键路径
void KeyPath(){
    printf("=====关键活动=====\n");
    for(int u=1;u<=n;u++){
        for(Edge *p=G[u];p;p=p->next){
            int v=p->to;
            int e = ve[u];
            int l = vl[v] - p->w;
            if(e == l){
                printf("关键活动:%d -> %d  权=%d\n",u,v,p->w);
            }
        }
    }
    printf("工程最短工期:%d\n",ve[topo[cnt]]);
}

int main(){
    scanf("%d%d",&n,&m);
    memset(G,0,sizeof(G));
    memset(in,0,sizeof(in));

    for(int i=1;i<=m;i++){
        int u,v,w;
        scanf("%d%d%d",&u,&v,&w);
        addEdge(u,v,w);
    }

    TopSort();
    getVE();
    getVL();
    KeyPath();
    return 0;
}

五、考点必背

  1. 关键路径仅存在于 AOE 有向无环图
  2. 关键路径 = 源点到汇点最长路径
  3. 关键活动:l−e=0
  4. 关键活动推迟→整体工期延长 ;非关键活动有时间余量,可适当延迟
  5. 拓扑求 ve,逆拓扑求 vl
  6. 关键路径可能多条
相关推荐
yi0118 小时前
LeetCode 219:存在重复元素 II——哈希表记录“最近一次出现的位置”
数据结构·人工智能·笔记·python·算法·leetcode·哈希表
禾小西10 小时前
Redis 数据结构:快速的 Redis 有哪些慢操作?
数据结构·数据库·redis
H.莓飛11 小时前
【数据结构】二叉树_OJ题
linux·开发语言·数据结构·算法
好想像大佬一样能够ak所有11 小时前
Leetcode35.搜索插入位置
数据结构·算法·leetcode
chenbingjie_c12 小时前
C++ STL 适配器:stack & queue,从 vector/list 到 deque 深度解析
数据结构·c++
垆边人似月.15 小时前
华为OD算法题:查找众数及中位数
数据结构·算法·leetcode
CoderYanger16 小时前
一轮复习——F.动态规划模型总结(入门篇)
java·开发语言·数据结构·算法·leetcode·职场和发展·动态规划
一只旭宝17 小时前
数据结构与算法复习手册:从写过,到讲清楚
开发语言·数据结构·c++·算法
All for pursuit.18 小时前
【动态规划-1】121.买卖股票的最佳时机
数据结构·c++·算法·leetcode·动态规划
Logic10118 小时前
C语言/数据结构位运算题解:异或XOR找出优秀项目组中的“独特编号“——只出现一次的数字
c语言·数据结构·数组·位运算·时间复杂度·算法题·异或性质