AOE网的关键路径的计算

简介:

求关键路径,只需理解顶点(事件)和边(活动)各自的两个特征属性以及求法即可:

   Ø  先根据首结点的Ve(j)=0由前向后(正拓扑序列)计算各顶点的最早发生时间

   Ø  再根据终结点的Vl(j)等于它的Ve(j)由后向前(逆序拓扑)依次求解各顶点的最晚发生时间

   Ø  根据边的ee(i)等于它的发出顶点的Ve(j)计算各边的最早开始时间(最早开始,对应最早发生)

   Ø  根据边的ll(i)等于它的到达顶点的Vl(j)减去边的权值计算各边的最晚开始时间(最晚开始,对应最晚发生)


#include<iostream>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<vector>
#include<stack>
#define MAX_NODE_NUM 100
using namespace std;

int first[MAX_NODE_NUM];
typedef struct EDGE{
    int u, v, w;
    int nextarc;
    EDGE(){
    }
    EDGE(int u, int v, int w, int nextarc){
        this->u = u;
        this->v = v;
        this->w = w;
        this->nextarc = nextarc;
    }
} edge;

vector<edge> g;
stack<int> s, t;//s存储入度为零的节点, t存储图的拓扑序列的顶点栈 

int ve[MAX_NODE_NUM];//事件的最早发生时间, 或者 活动ai的最早发生时间 
int vl[MAX_NODE_NUM];//事件的最晚发生时间 
int degIn[MAX_NODE_NUM];//记录每一个节点的入度 
int tag[MAX_NODE_NUM][MAX_NODE_NUM];
int n, m;//分别为图的节点的个数,和边的个数 

bool topoSort(){
    memset(ve, 0, sizeof(ve));
    int cnt = 0;//记录 
    for(int i=1; i<=n; ++i)
        if(degIn[i] == 0)
            s.push(i);
    while(!s.empty()){
        int u = s.top();
        s.pop();
        t.push(u);
        ++cnt;
        for(int e=first[u]; ~e; e=g[e].nextarc){
            int v = g[e].v;
            int w = g[e].w;
            if(--degIn[v] == 0) s.push(v);
            if(ve[u] + w > ve[v]) ve[v] = ve[u] + w;
        }
    }
    if(cnt < n) return false;//该有向图存在回路 
    return true;
}

bool criticalPath() {//寻找关键路径 
    if(!topoSort()) return false; 
    for(int i=1; i<=n; ++i)
        vl[i] = ve[t.top()];
    while(!t.empty()){//逆序拓扑排序,计算每个节点的最晚的发生时间 
        int u = t.top();
        t.pop();
        for(int e=first[u]; ~e; e=g[e].nextarc){
            int v = g[e].v;
            int w = g[e].w;
            if(vl[v] - w < vl[u]) vl[u] = vl[v] - w;
        }
    }
    
    for(int i=1; i<=n; ++i){//输出关节点 
        int ee = ve[i];//活动ai的最早的发生时间 
        for(int e=first[i]; ~e; e=g[e].nextarc) {
            int v = g[e].v;
            int w = g[e].w;
            int ll = vl[v]-w;//活动ai的最晚的发生时间 
            ll == ee ? printf(" * ") : printf("   ");
            printf("%d %d %d %d %d\n", i, v, w, ee, ll);//分别为 u, v, w(这条边所对应的活动), 活动最早发生时间和最晚发生时间 
        }
    } 
    return true;
}

void dfs(int u){
    for(int e=first[u]; ~e; e=g[e].nextarc) {
        int ee = ve[u];
        int v = g[e].v;
        int w = g[e].w;
        dfs(v);
        if(tag[u][v]) continue;
        tag[u][v] = 1;
        if(vl[v]-w < vl[u]) vl[u] = vl[v]-w;
        int ll = vl[v]-w;//活动au的最晚的发生时间 
        ll == ee ? printf(" * ") : printf("   ");
        printf("%d %d %d %d %d\n", u, v, w, ee, ll);
    }
}

bool criticalPathx() {//寻找关键路径,利用dfs可以 
    if(!topoSort()) return false; 
    for(int i=1; i<=n; ++i)
        vl[i] = ve[t.top()];
    dfs(1);//默认1节点为源点 
}

void addEdge(int u, int v, int w){
    edge e(u, v, w, first[u]);
    first[u] = g.size();
    g.push_back(e);
} 

int main(){
    printf("请输入图的节点的个数和边的个数:\n");
    scanf("%d%d", &n, &m);
    memset(first, -1, sizeof(first));
    while(m--){
        int u, v, w;
        scanf("%d %d %d", &u, &v, &w);
        addEdge(u, v, w);
        ++degIn[v];
    }
    //criticalPath();
    /*输出结果: 
         * 1 3 2 0 0
2 3 0 1
4 2 3 4
5 3 3 4
6 3 2 5
         * 3 4 4 2 2
         * 4 6 2 6 6
6 1 6 7
    */
    criticalPathx();
    /*输出结果:
6 3 2 5
     * 4 6 2 6 6
     * 3 4 4 2 2
     * 1 3 2 0 0
4 2 3 4
6 1 6 7
5 3 3 4
2 3 0 1
    */
    return 0;
}

输入数据:
8
2 3
5 3
6 1
4 2
6 2
4 4
3 2
6 3

目录
相关文章
|
缓存 安全 Docker
《Docker 简易速速上手小册》第3章 Dockerfile 与镜像构建(2024 最新版)
《Docker 简易速速上手小册》第3章 Dockerfile 与镜像构建(2024 最新版)
472 0
|
存储 Prometheus 监控
Centos7.X 搭建Prometheus+node_exporter+Grafana实时监控平台(下)
Centos7.X 搭建Prometheus+node_exporter+Grafana实时监控平台(下)
494 0
Centos7.X 搭建Prometheus+node_exporter+Grafana实时监控平台(下)
|
10月前
|
人工智能 搜索推荐 前端开发
6.2k tar 热门项目,揭秘:一篇 Markdown 如何秒生成 PPT、书籍、文章
Quarkdown是一款现代化Markdown排版系统,支持编程逻辑(如函数、变量、条件语句)嵌入文档,实现内容复用与动态生成。它可一键输出为PDF、HTML幻灯片、文章或书籍等多种格式,打破传统Markdown在排版、逻辑和格式上的局限。相比Pandoc+Lua、mdBook等工具,Quarkdown更易用且功能全面,适合学术论文、技术分享、知识管理及出版流程等场景。项目地址:[https://github.com/iamgio/quarkdown](https://github.com/iamgio/quarkdown)。
603 5
|
10月前
|
存储 Java C语言
Java List 复制:浅拷贝与深拷贝方法及区别
我是小假 期待与你的下一次相遇 ~
994 1
|
存储 人工智能 API
SPO:如何优化提示词?大模型最懂如何优化自己!开源自监督提示词优化工具,让AI自主优化提示词
本文介绍由DeepWisdom与香港科技大学联合研发的SPO框架,通过自我监督机制实现大语言模型提示优化,仅需3个样本即可达到SOTA效果,优化成本降低至传统方法的1.1%-5.6%。
2644 0
SPO:如何优化提示词?大模型最懂如何优化自己!开源自监督提示词优化工具,让AI自主优化提示词
Kam
|
算法 Java Linux
使用SecureRandom生成验证码随机数,线程阻塞问题记录
使用SecureRandom生成验证码随机数,线程阻塞问题记录
Kam
1209 0
|
存储 Ubuntu Java
【Linux】已解决:Ubuntu虚拟机安装Java/JDK
【Linux】已解决:Ubuntu虚拟机安装Java/JDK
1136 1
|
搜索推荐 关系型数据库 测试技术
PostgreSQL 全表 全字段 模糊查询的毫秒级高效实现 - 搜索引擎也颤抖了
标签 PostgreSQL , 分词 , 全文检索 , 全字段检索 , 任意字段检索 , 下拉框选择 , 搜索引擎 背景 在一些应用程序中,可能需要对表的所有字段进行检索,有些字段可能需要精准查询,有些字段可能需要模糊查询或全文检索。 比如一些前端页面下拉框的勾选和选择。 这种需求对于
15355 0
|
Java 应用服务中间件 Maven
【问题篇】IDEA运行war包项目
【问题篇】IDEA运行war包项目
1765 0