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

一、核心前提

  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. 关键路径可能多条
相关推荐
cfm_29148 小时前
Redis五大基本数据结构底层了解
数据结构·数据库·redis
如竟没有火炬8 小时前
最大矩阵——单调栈
数据结构·python·线性代数·算法·leetcode·矩阵
Lyyaoo.14 小时前
【数据结构】HashMap底层存储+扩容机制+线程安全【待更新】
数据结构·安全·哈希算法
如何原谅奋力过但无声14 小时前
【灵神高频面试题合集09-13】二叉树、二叉搜索树
数据结构·算法·leetcode
xqqxqxxq14 小时前
树结构技术学习笔记
数据结构·笔记·学习
小欣加油15 小时前
leetcode2161 根据给定数字划分数组
数据结构·c++·算法·leetcode·职场和发展
雨落在了我的手上15 小时前
Java数据结构(四):List的介绍
数据结构
大都督会赢的15 小时前
数据结构(2)--单链表
数据结构
cpp_250115 小时前
P2947 [USACO09MAR] Look Up S
数据结构·c++·算法·题解·单调栈·洛谷
小蒋学算法16 小时前
算法-乘法表中第K小的数-二分
数据结构·算法