关键路径

//关键路径
//E(i): 事件Vi可能的最早发生时间,它等同于从源点V1到Vi的最长路径长度
//L(i): 在保证结束点Vn在E(n)时刻发生的前提下,事件Vi允许的最晚发生时间,它等于E(n)-从顶点Vi到Vn的最长路径长度
//计算下面这两个两
//1 E(1)=0,然后沿着正向路径求E(j), E(j)=max{E(i)+Wij} , i<j<=n
//把所有的E(1..n) 都求出来.
//2 L(n)=E(n),然后反向求L(i), L(i)=min{L(j)-Wij} , i<j<=n

//关键路径的算法思路:
//1 从源点出发对网中顶点进行拓扑排序,在排序过程中,计算每个顶点的可能的最早发生时间
//  同时随时把入度为0的点的序号入栈,以便在排序结束后得到一个顶点的拓扑逆序.
//  当网中所有顶点都输出后,从保存顶点逆拓扑序列的栈中,依次弹出每个顶点的序号,计算各个顶点的最迟发生事件.以及各个活动的时间余量

//约定:
//1 AOE使用 邻接表
//2 E[1..n] : 每个顶点的最早发生时间
//3 L[1..n] : 每个顶点的最晚发生时间
//4 s 栈,t1 入栈的栈顶, t2 出栈的栈顶

//求关键路径
void criticalpath()
{
 float E[n0+1]; //节点的最早发生时间
 float L[n0+1]; //节点的最晚发生时间
 int s[n0+1];   //栈
 int t1 = -1;   //入栈栈顶
 int t2 = n0+1; //出栈栈顶
 arcnode* p;
 
 //求E[1..n]
 //初始化
 for(i=1;i<=n;i++)
 {
  E[i]=0;
 }

 s[++t1]=1; //入度为0的顶点入栈
 
 while(t1 >-1)
 {//如果栈不为空
  i=s[t1--];//出栈
  s[--t2]=i;//逆序的入栈

  p=adjlist[i].first; //得到第i个节点关联的边
  while(p)
  {//如果第i个节点关联的边不为空,把这些边对应的点的入度-1
   j=p->vertext; //边对应的点, i,j是有边相连接的
   adjlist[j].degree--;
   if(adjlist[j].degree == 0)
   {//如果j点的入度为0,入t1栈
    s[++t]=j;
   }
   if(E[j]<E[i]+p->weight)
   {//得到max的E[j]
    E[j] = E[i]+p->weight;
   }

   p=p->next;
  }
 }
 //到这里构造E[1..n]结束,构造s[t2]结束.

 //求L[1..n]
 //初始化
 for(i=1;i<=n;i++)
 {
  E[i]=L[n];
 }
 
 //一个拓扑逆序的过程
 while(t2<n0+1)
 {//当t2栈不为空,注意t2栈是一个逆序
  i=s[t2++]; //t2栈出栈
  p=adjlist[i].first;    //这里的adjlist[i] 和上面的 adjlist[j]是 逆序的存储
  while(p)
  {
   j = p->vertext;
   if(L[i]>L[j]-p->weight)
   {//求最小的
    L[i]=L[j]-p->weight;
   }
   p=p->next;
  }
 }
 //到这里就得到了L[1..n]
 //下面输出所有的关键节点
 for(i=1;i<=n;i++)
 {
  p= adjlist[i].first; //p是i节点连接的边
  while(p)
  {//如果这个边存在,要判断这个边是不是关键边,关键边就是关键路径
   j=p->vertext;//j是这个边的另外一个节点,这条边是(i,j)
   if(L[j] == E[i]+p->weight)
   {//如果最晚结束时间 = 最早开始时间 + 需要时间 -> 这条边就是关键的
    cout<<"<"<<i<<","<<j<<">"<<endl;
   }
   p = p->next;
  }
 }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值