学习笔记——关键路径

关键路径:

  • AOE-网
  • AOE-网中的基本概念
  • 几个重要的定义
  • 求关键路径的基本步骤
  • 修改后的拓扑排序算法
  • 求关键路径的实现算法

AOE-网:

在有向图中,用顶点表示事件,用弧表示活动,弧的权值表示活动所需要的时间。这种有向无环图叫做边表示活动的网,简称AOE-网。

AOE-网中的基本概念:

源点:存在唯一的、入度为0的顶点,叫源点。
汇点:存在唯一的、出度为0的顶点,叫汇点。
关键路径:从源点到汇点的最长路径的长度即为完成整个工程任务所需的时间,该路径叫做关键路径。
关键活动:关键路径上的活动叫做关键活动。

几个重要的定义:

ve(i):事件vi的最早发生时间,即从源点到顶点vi的最长路径的长度。—求ve(i)时可以从源点开始,按拓扑排序向汇点递推:
ve(0)=0;
ve(i)=Max{ve(k)+dut()};
dut()为k点到 j 点的持续时间或边权;

vl(i):事件vi的最晚发生时间。—在求出ve(i)的基础上,可以从汇点开始,按逆拓扑排序向源点递推:vl(n-1)=ve(n-1);
vl(i)=Min{vl(k)-dut()};

e(i):活动ai的最早开始时间。—如果活动ai对应的弧为,则e(i)等于从源点到顶点j的最长路径的长度,即e(i)=ve(j);

l(i):活动ai的最晚开始时间。—如果活动ai对应的弧为,其持续时间为dut(),则:l(i)=vl(k)-dut();

活动ai的松弛时间:等于l(i)-e(i);

求关键路径的基本步骤:

1、对图中顶点进行拓扑排序,在排序过程中按拓扑序列求出每个事件的最早发生时间ve(i);
2、按逆拓扑序列求出每个事件的最晚发生时间vl(i);
3、求出每个活动ai的最早开始时间e(i)和最晚开始时间l(i);
4、找出e(i)=l(i)的活动ai,即为关键活动;

修改后的拓扑排序算法:

int ve[MAX];/*每个顶点的最早发生时间*/
int TopoOrder(AdjList G,Stack *T)/*T为返回拓扑序列的栈,S为存放入度为0的顶点的栈*/
{ Stack S;
  int indegree[MAX];
  int i,j,count,k;
  ArcNode *p;
  FindID(G,indegree);/*求各顶点入度*/
  InitStack(T);
  InitStack(&S);
  for(i=0;i<G.vexnum;i++){
     if(indegree[i]==0)
     Push(&S,i);/*将入度为0的顶点入栈*/
     count=0;
  for(j=0;j<G.vexnum;j++){
      ve[j]=0;/*初始化*/
  while(!StackEmpty(S))
   {  Pop(&S,&j);
      Push(T,j);/*拓扑序列的点入T栈*/
      count++;
      p=G.vertex[j].firstarc;
      while(p!==NULL)
      { k=p->adjvex;
        indegree[k]--;
        if(indegree[k]==0)
        Push(&S,k);/*若入度减为0,则入栈*/
        if(ve[k]+p->weight>ve[k])
           ve[k]=ve[j]+p->weight;/*事件最早发生时间的计算*/
        p=p->nextarc;
        }
    } } }
   if(count<G.vexnum)
      return(Error);
    else return(Ok);
}

求关键路径的实现算法:

int CriticalPath(AdjList G)
{ ArcNode *p;
  Stack T;
  int vl[MAX];
  int i,j,k,dut,ei,li;
  if(!TopoOrder(G,&T))
     return(Error);
  for(i=0;i<G.vexnum;i++){
     vl[i]=ve[i];/*初始化*/
     while(!StackEmpty(T))
   {  Pop(&T,&i);/*通过出栈得到逆拓扑序列*/
      p=G.vertex[i].firstarc;/*i号顶点的弧*/
      while(p!==NULL)
      { k=p->adjvex;
        dut=p->weight;
        if(vl[k]-dut<vl[i])/*事件最晚发生时间的计算*/
           vl[i]=vl[k]-dut;
        p=p->nextarc;
        }
    }  }
   for(j=0;j<G.vexnum;j++){
      p=G.vertex[j].firstarc;
      while(p!=NULL)
      { k=p->adjnex;
        dut=p->weight;
        ei=ve[j];
        li=vl[k]-dut;
        tag=(ei==li)?'*':' ';/*如果ei等于li即为关键活动,标记为*,否则标记为空格*/
        printf("%c,%c,%d,%d,%d,%c\n",G.vertex[j].data,G.vertex[k].data,dut,ei,li,tag);
        /*输出关键活动*/
        p=p->nextarc;
      }
    }
    return(Ok);
}

你可能感兴趣的:(数据结构与算法)