5 AOE网&关键路径

图论 —— AOE 网与关键路径_aoe缩短工期-CSDN博客

【数据结构】AOE网——关键路径_aoe网的关键路径-CSDN博客

语雀版本

1 概念

**AOE网**: Activity On Edge Network,边表示活动的网。边是活动,顶点是事件(活动完成)。边带权,表示活动完成需要的时间。

源点:入度为0的点。

汇点:出度为0的点。

关键路径:从源点到汇点的最长路径。该路径的时间是整个工程完成的时间。

关键活动:关键路径上的活动。这些活动制约了工程的工期。

2 关键路径算法

**事件的最早发生时间:**某个点k的ve(k)等于其前驱点加对应边权的最大值。表示该事件发生的最早时间。

ve(源点)=0

ve(k) = max{ve(i)+cost(i,k)}

事件的最晚发生时间:某个点k的vl(k)等于其后继点-对应边权的最小值,表示在不影响工期的前提下该事件发生的最晚时间。

vl(汇点) = ve(汇点)

vl(k) = min{vl(j) - cost(k, j)}

活动的最早发生时间:某条边i的最早发生事件为起点的事件的最早发生时间。

活动为(k, j),则 e(i) = ve(k)

活动的最晚发生时间:某条边i的最早发生事件为终点的事件的最迟发生时间减该边i的时间。

活动为(k, j),则 l(i) = vl(j) - cost(k, j)

3 **代码**

3.1 **关键路径**

从源点求事件的最早发生时间ve->从汇点求事件的最晚发生时间vl->求活动的最早发生时间e->求活动的最晚发生时间l->找出e=l的边即为关键路径。
int n,m;
int G[N][N];//邻接矩阵
int in[N];//入度
int ve[N];//事件vk的最早发生时间
int vl[N];//事件vk的最晚发生时间
int ee[N];//活动ai的最早开始时间
int el[N];//活动ai的最晚开始时间
int Stack[N];//栈
struct Edge {
    int x,y;
    int dis;
    Edge(){}
    Edge(int x,int y,int dis):x(x),y(y),dis(dis){}
}edge[N];
bool vis[N];
 
void getVe(){//求ve
    int cnt=0;
    for(int i=1;i<=n;i++){
        int k=-1;
        for(int j=1;j<=n;j++){
            if(in[j]==0){
                Stack[++cnt]=j;
                k=j;
                in[j]=-1;
                break;
            }
        }
        for(int j=1;j<=n;j++){
            if(G[k][j]!=INF){
                ve[j]=max(ve[j],ve[k]+G[k][j]);
                in[j]--;
            }
        }
    }
}
void getVl(){//求vl
    memset(vl,INF,sizeof(vl));
    vl[Stack[n]]=ve[Stack[n]];
    for(int i=n;i>=1;i--){
        for(int j=1;j<=n;j++){
            if(G[Stack[i]][j]!=INF) {
                vl[Stack[i]]=min(vl[j]-G[Stack[i]][j],vl[Stack[i]]);
            }
        }
    }
}
void getEe(){//求ee
    for(int i=1;i<=m;i++)
        ee[i]=ve[edge[i].x];
}
void getEl(){//求el
    for(int i=1;i<=m;i++)
        el[i]=vl[edge[i].y]-edge[i].dis;
}
 
void printEdge(){//以边输出
    for(int i=1;i<=m;i++)
        if(ee[i]==el[i])
            printf("<%d,%d>:%d\n", edge[i].x, edge[i].y, edge[i].dis);
}
void printNode(){//以点输出
    priority_queue<int,vector<int>,greater<int> > Q;
    memset(vis,false,sizeof(vis));
    for(int i=1;i<=m;i++){
        if(ee[i]==el[i]){
            int x=edge[i].x;
            int y=edge[i].y;
            if(!vis[x]){
                Q.push(x);
                vis[x]=true;
            }
            if(!vis[y]){
                Q.push(y);
                vis[y]=true;
            }
        }
    }
    while(!Q.empty()){
        int temp=Q.top();
        Q.pop();
        printf("v%d ",temp);
    }
}
int main() {
    memset(G,INF,sizeof(G));
 
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++){
        int x,y,dis;
        scanf("%d%d%d",&x,&y,&dis);
        edge[i].x=x;
        edge[i].y=y;
        edge[i].dis=dis;
 
        G[x][y]=dis;
        in[y]++;
    }
 
    getVe();
    getVl();
    getEe();
    getEl();
 
    printf("以边输出:\n");
    printEdge();
    printf("以点输出:\n");
    printNode();
 
    return 0;
}

3.2 关键路径的长度

实际上求出ve,然后找打汇点的ve值就可以了
#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;

// 关键路径算法
int criticalPath(int n, vector<vector<int>>& edges) {
    // 邻接表表示图
    vector<vector<pair<int, int>>> graph(n);
    // 入度数组
    vector<int> inDegree(n, 0);
    // 最长路径数组
    vector<int> dist(n, 0);
    
    // 建立图
    for (const auto& edge : edges) {
        int u = edge[0], v = edge[1], w = edge[2];
        graph[u].emplace_back(v, w);
        inDegree[v]++;
    }
    
    // 拓扑排序队列
    queue<int> q;
    // 将入度为0的节点加入队列
    for (int i = 0; i < n; ++i) {
        if (inDegree[i] == 0) {
            q.push(i);
        }
    }
    
    // 拓扑排序并计算最长路径
    while (!q.empty()) {
        int node = q.front();
        q.pop();
        
        for (const auto& neighbor : graph[node]) {
            int v = neighbor.first;
            int weight = neighbor.second;
            // 更新最长路径
            dist[v] = max(dist[v], dist[node] + weight);
            // 入度减1
            inDegree[v]--;
            // 如果入度为0,加入队列
            if (inDegree[v] == 0) {
                q.push(v);
            }
        }
    }
    
    // 找到最长路径的长度
    return *max_element(dist.begin(), dist.end());
}

int main() {
    // 示例输入:节点数量和边
    int n = 6;
    vector<vector<int>> edges = {
        {0, 1, 3}, {0, 2, 2}, {1, 3, 2}, {2, 3, 4},
        {3, 4, 2}, {3, 5, 3}, {4, 5, 1}
    };
    
    int result = criticalPath(n, edges);
    cout << "关键路径的长度为: " << result << endl;
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Zx-Chen

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

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

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

打赏作者

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

抵扣说明:

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

余额充值