- // PivotalPath.cpp : Defines the entry point for the console application.
- //
- //问题描述:关键路径实现<有向图>
- //创建者:QGX
- //创建时间:2008-2-12
- #include "stdafx.h"
- #include<iostream>
- #include<cassert>
- #include"F:/QGX_TEMP/HEADFILE/STACK.h"
- using namespace std;
- #define N 9
- #define INFINIT 30000 //无穷大
- bool PriTime(int G[N+1][N+1],int PT[])
- {
- //求每个节点的最早发生时刻
- int vcount=0;//已经找到最早开始时间的节点
- for(int i=1;i<=N;i++)
- PT[i]=-1;//假定最早发生时刻
- PT[1]=0;
- STACK<int> *S=new STACK<int>(N);//申请一个栈
- if(!S)exit(1);
- int *indegree=new int[N+1];//图中每个顶点的入度
- if(!indegree)exit(1);
- for(int i=2;i<=N;i++)
- {
- indegree[i]=0;
- for(int j=1;j<=N;j++)
- if(j!=i && G[j][i]>0 && G[j][i]<INFINIT)indegree[i]++;
- }
- S->push(1);//起始顶点入栈
- while(!S->empty() && vcount<N)
- {
- int temp;
- if(S->pop(temp))NULL;
- vcount++;
- for(int k=2;k<=N;k++)
- {
- if(temp!=k && G[temp][k]>0 && G[temp][k]<INFINIT)
- {
- indegree[k]--;
- if(G[temp][k]+PT[temp]>PT[k])PT[k]=G[temp][k]+PT[temp];
- if(!indegree[k])S->push(k);
- }
- }
- }
- delete[] indegree;
- delete S;
- return vcount>=N;
- }
- bool LasTime(int G[N+1][N+1],int MAXPATH,int LT[])
- {
- //MAXPATH即是PT[N]
- //求每个节点的最迟开始时刻
- //逆拓扑排序的方法
- int vcount=0;
- for(int k=1;k<=N;k++)
- LT[k]=MAXPATH; //初始为永不开始
- STACK<int> *S=new STACK<int>(N);//申请一个栈
- if(!S)exit(1);
- int *outdegree=new int[N+1];//图中每个顶点的出度
- if(!outdegree)exit(1);
- for(int i=1;i<=N;i++)
- { //求得每个节点的出度
- outdegree[i]=0;
- for(int j=1;j<=N;j++)
- if(G[i][j]>0 && G[i][j]<INFINIT)outdegree[i]++;
- }
- S->push(N);//终点入栈
- while(!S->empty() && vcount<N)
- {
- int temp;
- if(S->pop(temp))NULL;
- vcount++;
- for(int k=1;k<N;k++)
- {
- if(temp!=k && G[k][temp]>0 && G[k][temp]<INFINIT)
- {
- outdegree[k]--;
- if(LT[temp]-G[k][temp]<LT[k])LT[k]=LT[temp]-G[k][temp];
- if(!outdegree[k])S->push(k);
- }
- }
- }
- delete[] outdegree;
- delete S;
- return vcount>=N;
- }
- bool pivotalpath(int G[N+1][N+1],int path[],int &size)
- {
- //求关键路径
- //m为G的维数
- //不失一般性,令顶点1与顶点N分别代表关键路径的起点与终点
- assert(N>0);
- int *pt=new int[N+1];//每个节点的最早开始时刻
- if(!pt)exit(1);
- int *lt=new int[N+1];//每个节点的最迟开始时刻
- if(!lt)exit(1);
- /*--------利用拓扑排序方法求得每个节点的最早发生时间------*/
- if(!PriTime(G,pt)){ delete[] lt;delete[] pt;return false;}
- //cout<<"每个节点的最早开始时刻为:"<<endl;
- //for(int i=1;i<=N;i++)
- // cout<<pt[i]<<endl;
- cout<<"此有向图从起点到终点的最长路径长度为:"<<pt[N]<<endl;
- /*--------求每个节点的最迟发生时间-------*/
- if(!LasTime(G,pt[N],lt)){delete[] lt;delete[] pt;return false;}
- //cout<<"每个节点的最晚开始时刻为:"<<endl;
- //for(int i=1;i<=N;i++)
- // cout<<lt[i]<<endl;
- /*---------判断哪些为关键节点-----------*/
- size=0;
- for(int k=1;k<=N;k++)
- if(pt[k]==lt[k])path[size++]=k;
- delete[] lt;
- delete[] pt;
- return true;
- }
- void INIT_TEXT(int G[N+1][N+1])
- {
- //一个测试数据
- G[1][2]=6;G[1][3]=4;G[1][4]=5;G[2][5]=1;G[3][5]=1;G[4][6]=2;
- G[5][7]=9;G[5][8]=7;G[6][8]=4;G[7][9]=2;G[8][9]=4;
- }
- int _tmain(int argc, _TCHAR* argv[])
- {
- int G[N+1][N+1]={-1};//存储有向图信息,G[i][j]==-1,则表示i不是j的直接前驱,否则则表示存在一个从i到j的活动
- int P[N+1];
- int edges,x,y,value,pathsize;
- INIT_TEXT(G);
- //cout<<"请输入此"<<N<<"维有向图的弧的个数和每个弧的信息"<<endl;
- //cin>>edges;
- //assert(edges>0);
- //for(int i=0;i<edges;i++)
- //{
- // cin>>x>>y>>value;
- // if(x<1 || x>N || y<1 || y>N || value<=0 || value>=INFINIT){cout<<"参数不合法,请重新输入"<<endl;--i;continue;}
- // else G[x][y]=value;
- //}
- if(!pivotalpath(G,P,pathsize)){cout<<"此有向图不存在关键路径!"<<endl;}
- else
- {
- cout<<"此有向图的关键路径节点序为"<<endl;
- for(int k=0;k<pathsize-1;k++)
- cout<<P[k]<<"->";
- cout<<P[pathsize-1]<<endl;
- }
- getchar();
- return 0;
- }
关键路径实现
最新推荐文章于 2021-02-12 23:36:00 发布