zoukankan      html  css  js  c++  java
  • 关键路径

    工程中的关键活动和关键路径

    #include <iostream>
    using namespace std;
    
    #define MVNum 100                           //最大顶点数
    #define BDNum MVNum * (MVNum - 1)            //最大边数
    #define OK 1    
    #define ERROR 0 
    
    typedef char VerTexType;
    
    //- - - - -图的邻接表存储表示- - - - - 
    typedef struct ArcNode {                        
        int adjvex;                          
        int weight;                                
        struct ArcNode *nextarc;                  
    }ArcNode;
    
    typedef struct VNode {
        VerTexType data;                        
        ArcNode *firstarc;                        
    }VNode, AdjList[MVNum];                       
    
    typedef struct {
        AdjList vertices;                         //邻接表 
        AdjList converse_vertices;                //逆邻接表
        int vexnum, arcnum;                      //图的当前顶点数和边数 
    }ALGraph;
    
    //- - - - -顺序栈的定义- - - - -
    typedef struct {
        int *base;
        int *top;
        int stacksize;
    }spStack;
    
    int indegree[MVNum];                        //数组indegree存放个顶点的入度
    int ve[BDNum];                                //事件vi的最早发生时间
    int vl[BDNum];                                //事件vi的最迟发生时间
    int topo[MVNum];                            //记录拓扑序列的顶点序号
    spStack S;
    
    //----------------栈的操作--------------------
    void InitStack(spStack &S) {
        //栈的初始化
        S.base = new int[MVNum];
        if (!S.base)
            exit(1);
        S.top = S.base;
        S.stacksize = MVNum;
    }
    
    void Push(spStack &S, int i) {
        //入栈
        if (S.top - S.base == S.stacksize)
            return;
        *S.top++ = i;
    }
    
    void Pop(spStack &S, int &i) {
        //出栈
        if (S.top == S.base)
            return;
        i = *--S.top;
    }
    
    bool StackEmpty(spStack S) {
        //判断栈是否为空
        if (S.top == S.base)
            return true;
        return false;
    }
    
    
    int LocateVex(ALGraph G, VerTexType v) {
        //确定点v在G中的位置
        for (int i = 0; i < G.vexnum; ++i)
            if (G.vertices[i].data == v)
                return i;
        return -1;
    }
    
    int CreateUDG(ALGraph &G) {
        //创建有向图G的邻接表、逆邻接表
        int i, k;
    
        cout << "请输入总顶点数:";
        cin >> G.vexnum;
        cout << "请输入弧数:";
        cin >> G.arcnum;
        cout << "请依次输入各顶点:";
        for (i = 0; i < G.vexnum; ++i) {                  //输入各点,构造表头结点表
            cin >> G.vertices[i].data;                   //输入顶点值
            G.converse_vertices[i].data = G.vertices[i].data;
            //初始化表头结点的指针域为NULL 
            G.vertices[i].firstarc = NULL;
            G.converse_vertices[i].firstarc = NULL;
        }
    
        cout << "请输入各条弧和对应的权值:" << endl;
    
        for (k = 0; k < G.arcnum; ++k) {                    
            VerTexType v1, v2;
            int i, j, w;
            cin >> v1 >> v2 >> w;                    
            i = LocateVex(G, v1);  j = LocateVex(G, v2);
            ArcNode *p1 = new ArcNode;                   
            p1->adjvex = j;                               
            p1->nextarc = G.vertices[i].firstarc;  G.vertices[i].firstarc = p1;
            p1->weight = w;
            ArcNode *p2 = new ArcNode;                       
            p2->adjvex = i;                               
            p2->nextarc = G.converse_vertices[j].firstarc;  G.converse_vertices[j].firstarc = p2;
            p2->weight = w;
            
        }
        return OK;
    }
    
    void FindInDegree(ALGraph G) {
        //求出各顶点的入度存入数组indegree中 
        int i, count;
    
        for (i = 0; i < G.vexnum; i++) {
            count = 0;
            ArcNode *p = G.vertices[i].firstarc;
            if (p) {
                while (p) {
                    p = p->nextarc;
                    count++;
                }
            }
            indegree[i] = count;
        }
    }
    
    int TopologicalOrder(ALGraph G, int topo[]) {
        //有向图G采用邻接表存储结构 
        //若G无回路,则生成G的一个拓扑序列topo[]并返回OK,否则ERROR 
        int i, m;
        FindInDegree(G);                              //求出各顶点的入度存入数组indegree中 
        InitStack(S);                                  //栈S初始化为空 
        for (i = 0; i < G.vexnum; ++i)
            if (!indegree[i]) Push(S, i);             //入度为0者进栈 
        m = 0;                                       //对输出顶点计数,初始为0 
        while (!StackEmpty(S)) {                        //栈S非空 
            Pop(S, i);                              //将栈顶顶点vi出栈
            topo[m] = i;                                 //将vi保存在拓扑序列数组topo中 
            ++m;                                     //对输出顶点计数 
            ArcNode *p = G.vertices[i].firstarc;    //p指向vi的第一个邻接点 
            while (p) {
                int k = p->adjvex;                    //vk为vi的邻接点   
                --indegree[k];                       //vi的每个邻接点的入度减1 
                if (indegree[k] == 0)  Push(S, k);    //若入度减为0,则入栈 
                p = p->nextarc;                        //p指向顶点vi下一个邻接结点 
            }
        }
    
        if (m < G.vexnum)  return ERROR;                //该有向图有回路 
        else return OK;
    }
    
    int CriticalPath(ALGraph G) {
        //G为邻接表存储的有向网,输出G的各项关键活动
        int n, i, k, j, e, l;
        if (!TopologicalOrder(G, topo))  return ERROR;
        //调用拓扑排序算法,使拓扑序列保存在topo中,若调用失败,则存在有向环,返回ERROR 
        n = G.vexnum;                                  //n为顶点个数 
        for (i = 0; i < n; i++)                       //给每个事件的最早发生时间置初值0 
            ve[i] = 0;
    
    
        /*――――――――――按拓扑次序求每个事件的最早发生时间-――――-―――――*/
        for (i = 0; i < n; i++) {
            k = topo[i];                               //取得拓扑序列中的顶点序号k             
            ArcNode *p = G.vertices[k].firstarc;    //p指向k的第一个邻接顶点  
            while (p != NULL) {                        //依次更新k的所有邻接顶点的最早发生时间   
                j = p->adjvex;                       //j为邻接顶点的序号                   
                if (ve[j] < ve[k] + p->weight)        //更新顶点j的最早发生时间ve[j] 
                    ve[j] = ve[k] + p->weight;
                p = p->nextarc;                      //p指向k的下一个邻接顶点  
            }  
        }  
    
        for (i = 0; i<n; i++)                             //给每个事件的最迟发生时间置初值ve[n-1] 
            vl[i] = ve[n - 1];
    
        /*――――――――――按逆拓扑次序求每个事件的最迟发生时间-――――-―――――*/
        for (i = n - 1; i >= 0; i--) {
            k = topo[i];                               //取得拓扑序列中的顶点序号k             
            ArcNode *p = G.vertices[k].firstarc;    //p指向k的第一个邻接顶点  
            while (p != NULL) {                        //根据k的邻接点,更新k的最迟发生时间   
                j = p->adjvex;                      //j为邻接顶点的序号                   
                if (vl[k] > vl[j] - p->weight)        //更新顶点k的最迟发生时间vl[k] 
                    vl[k] = vl[j] - p->weight;
                p = p->nextarc;                      //p指向k的下一个邻接顶点  
            }
        } 
    
         /*――――――――――――判断每一活动是否为关键活动-――――――-―――――*/
        cout << "关键路径为:" << endl;
        for (i = 0; i < n; i++) {                        //每次循环针对vi为活动开始点的所有活动 
            ArcNode *p = G.vertices[i].firstarc;    //p指向i的第一个邻接顶点  
            while (p != NULL) {
                j = p->adjvex;                         //j为i的邻接顶点的序号    
                e = ve[i];                             //计算活动<vi, vj>的最早开始时间 
                l = vl[j] - p->weight;              //计算活动<vi, vj>的最迟开始时间 
                if (e == l)                           //若为关键活动,则输出<vi, vj> 
                    cout << G.vertices[i].data << G.vertices[j].data << " ";
                p = p->nextarc;                      //p指向i的下一个邻接顶点  
            } 
        }  
        return OK;
    }
    
    int main()
    {
        ALGraph G;
        CreateUDG(G);               
        if (!CriticalPath(G))
            cout << "网中存在环,无法进行拓扑排序!" << endl;
        return OK;
    }
  • 相关阅读:
    移除jboss响应中的中间件信息
    Cypress web自动化1-windows环境npm安装Cypress
    pytest文档39-参数化(parametrize)结合allure.title()生成不同标题报告
    pytest文档38-allure.step()添加测试用例步骤
    python笔记45-经典面试题:判断字符串括号是否闭合{}[]()
    Linux学习28-linux一行命令杀掉指定名称进程(killall 、kill 、pkill)
    pytest文档37-自定义用例顺序(pytest-ordering)
    pytest文档36-断言失败后还能继续执行pytest-assume
    pytest文档35-Hooks函数之统计测试结果(pytest_terminal_summary)
    pytest文档34-Hooks函数改变用例执行顺序(pytest_collection_modifyitems)
  • 原文地址:https://www.cnblogs.com/cjwen/p/11177871.html
Copyright © 2011-2022 走看看