关键路径

匿名 (未验证) 提交于 2019-12-02 23:48:02

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

#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; }

 

转载请标明出处:关键路径
文章来源: 关键路径
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!