关键路径实现

  1.  // PivotalPath.cpp : Defines the entry point for the console application.
  2. //
  3. //问题描述:关键路径实现<有向图>
  4. //创建者:QGX
  5. //创建时间:2008-2-12
  6. #include "stdafx.h"
  7. #include<iostream>
  8. #include<cassert>
  9. #include"F:/QGX_TEMP/HEADFILE/STACK.h"
  10. using namespace std;
  11. #define N 9
  12. #define INFINIT 30000 //无穷大
  13. bool PriTime(int G[N+1][N+1],int PT[])
  14.  //求每个节点的最早发生时刻
  15.  int vcount=0;//已经找到最早开始时间的节点
  16.  for(int i=1;i<=N;i++)
  17.   PT[i]=-1;//假定最早发生时刻
  18.  PT[1]=0;
  19.  STACK<int> *S=new STACK<int>(N);//申请一个栈
  20.  if(!S)exit(1);
  21.  int *indegree=new int[N+1];//图中每个顶点的入度
  22.  if(!indegree)exit(1);
  23.  for(int i=2;i<=N;i++)
  24.  {
  25.   indegree[i]=0;
  26.   for(int j=1;j<=N;j++)
  27.    if(j!=i && G[j][i]>0 && G[j][i]<INFINIT)indegree[i]++;
  28.  }
  29.  S->push(1);//起始顶点入栈
  30.  while(!S->empty() && vcount<N)
  31.  {
  32.   int temp;
  33.   if(S->pop(temp))NULL;
  34.   vcount++;
  35.   for(int k=2;k<=N;k++)
  36.   {
  37.    if(temp!=k && G[temp][k]>0 && G[temp][k]<INFINIT)
  38.    {
  39.     indegree[k]--;
  40.     if(G[temp][k]+PT[temp]>PT[k])PT[k]=G[temp][k]+PT[temp];
  41.     if(!indegree[k])S->push(k);
  42.    }
  43.   }
  44.  } 
  45.  delete[] indegree;
  46.  delete S;
  47.  return vcount>=N;
  48. }
  49. bool LasTime(int G[N+1][N+1],int MAXPATH,int LT[])
  50. {
  51.  //MAXPATH即是PT[N]
  52.  //求每个节点的最迟开始时刻
  53.  //逆拓扑排序的方法
  54.  int vcount=0;
  55.  for(int k=1;k<=N;k++)
  56.   LT[k]=MAXPATH; //初始为永不开始
  57.    
  58.  STACK<int> *S=new STACK<int>(N);//申请一个栈
  59.  if(!S)exit(1);
  60.  int *outdegree=new int[N+1];//图中每个顶点的出度
  61.  if(!outdegree)exit(1);
  62.  for(int i=1;i<=N;i++)
  63.  { //求得每个节点的出度
  64.   outdegree[i]=0;
  65.   for(int j=1;j<=N;j++)
  66.    if(G[i][j]>0 && G[i][j]<INFINIT)outdegree[i]++;
  67.  }
  68.  S->push(N);//终点入栈
  69.  while(!S->empty() && vcount<N)
  70.  {
  71.   int temp;
  72.   if(S->pop(temp))NULL;
  73.   vcount++;
  74.   for(int k=1;k<N;k++)
  75.   {
  76.    if(temp!=k && G[k][temp]>0 && G[k][temp]<INFINIT)
  77.    {
  78.     outdegree[k]--;
  79.     if(LT[temp]-G[k][temp]<LT[k])LT[k]=LT[temp]-G[k][temp];
  80.     if(!outdegree[k])S->push(k);
  81.    }
  82.   }
  83.  }
  84.  delete[] outdegree;
  85.  delete S;
  86.  return vcount>=N;
  87. }
  88. bool pivotalpath(int G[N+1][N+1],int path[],int &size)
  89. {
  90.  //求关键路径
  91.  //m为G的维数
  92.  //不失一般性,令顶点1与顶点N分别代表关键路径的起点与终点
  93.  assert(N>0);
  94.  int *pt=new int[N+1];//每个节点的最早开始时刻
  95.  if(!pt)exit(1);
  96.  int *lt=new int[N+1];//每个节点的最迟开始时刻
  97.  if(!lt)exit(1);
  98.  
  99.  /*--------利用拓扑排序方法求得每个节点的最早发生时间------*/
  100.  if(!PriTime(G,pt)){ delete[] lt;delete[] pt;return false;}
  101.  //cout<<"每个节点的最早开始时刻为:"<<endl;
  102.  //for(int i=1;i<=N;i++)
  103.  // cout<<pt[i]<<endl;
  104.    
  105.  cout<<"此有向图从起点到终点的最长路径长度为:"<<pt[N]<<endl;
  106.     /*--------求每个节点的最迟发生时间-------*/
  107.  if(!LasTime(G,pt[N],lt)){delete[] lt;delete[] pt;return false;}
  108.  //cout<<"每个节点的最晚开始时刻为:"<<endl;
  109.  //for(int i=1;i<=N;i++)
  110.  // cout<<lt[i]<<endl;
  111.  
  112.  /*---------判断哪些为关键节点-----------*/
  113.  size=0;
  114.  for(int k=1;k<=N;k++)
  115.   if(pt[k]==lt[k])path[size++]=k;
  116.  delete[] lt;
  117.  delete[] pt;
  118.  return true;
  119. }
  120. void INIT_TEXT(int G[N+1][N+1])
  121. {
  122.  //一个测试数据
  123.  G[1][2]=6;G[1][3]=4;G[1][4]=5;G[2][5]=1;G[3][5]=1;G[4][6]=2;
  124.  G[5][7]=9;G[5][8]=7;G[6][8]=4;G[7][9]=2;G[8][9]=4;
  125. }
  126. int _tmain(int argc, _TCHAR* argv[])
  127. {
  128.  int G[N+1][N+1]={-1};//存储有向图信息,G[i][j]==-1,则表示i不是j的直接前驱,否则则表示存在一个从i到j的活动 
  129.  int P[N+1];
  130.  int edges,x,y,value,pathsize; 
  131.  INIT_TEXT(G);
  132.  //cout<<"请输入此"<<N<<"维有向图的弧的个数和每个弧的信息"<<endl;
  133.  //cin>>edges;
  134.  //assert(edges>0);
  135.  //for(int i=0;i<edges;i++)
  136.  //{
  137.  // cin>>x>>y>>value;
  138.  // if(x<1 || x>N || y<1 || y>N || value<=0 || value>=INFINIT){cout<<"参数不合法,请重新输入"<<endl;--i;continue;}
  139.  // else G[x][y]=value;
  140.  //}
  141.  if(!pivotalpath(G,P,pathsize)){cout<<"此有向图不存在关键路径!"<<endl;}
  142.  else
  143.  {
  144.   cout<<"此有向图的关键路径节点序为"<<endl;
  145.   for(int k=0;k<pathsize-1;k++)
  146.    cout<<P[k]<<"->";
  147.   cout<<P[pathsize-1]<<endl;
  148.  }
  149.  getchar();
  150.  return 0;
  151. }
  152.  

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值