#include <iostream> #include <iomanip> #include <stack> using namespace std; #define MAX 100 typedef char VertexType; typedef struct ArcNode { int adjvex; //邻接点域,存储该弧指向顶点的下标 (终点) struct ArcNode *next; //指向下一条弧的指针 int weight; //权重 }ArcNode; //边结构 typedef struct VertexNode { VertexType data; //数据域 ArcNode *firstArc; //指向第一条依附该顶点的弧的指针 }VertexNode,AdjVerList[MAX]; typedef struct { AdjVerList vertices; //顶点集 int vexnum,arcnum; //图的顶点数和弧数 }ALGraph; //图结构 int ve[MAX]; //各事件的最早发生时间 void CreateALGraph(ALGraph *G); void Display(ALGraph *G); int CriticalPath(ALGraph *G); /* 求关键路径的基本步骤: 1.对图中顶点进行拓扑排序,在排序过程中按拓扑系列求出每个事件的最早发生事件ve(i) 2.按逆拓扑序列求出每个事件的最晚发生时间vl(i) 3.求出每个活动i的最早开始时间 e(i)和最晚发生时间l(i) 4.找到e(i)=l(i)的活动,即为关键路径 */ int main() { ALGraph G; CreateALGraph(&G); CriticalPath(&G); return 0; } //求顶点位置函数 int LocateVex(ALGraph *G,VertexType v) { int i; for(i=0;i<G->vexnum;i++) { if(G->vertices[i].data == v) return i; } return -1; } //有向无环图 void CreateALGraph(ALGraph *G) { VertexType v1,v2; int w; ArcNode *Arc; cout<<"请输入顶点数和边数:"; cin>>G->vexnum>>G->arcnum; cout<<"请输入各顶点的数据:"; for(int i=0;i<G->vexnum;i++){ cin>>G->vertices[i].data; G->vertices[i].firstArc = NULL; //顶点的边表设为空 } cout<<"请依次输入"<<G->arcnum<<"组边对应的两个顶点以及权值,以空格分割:"<<endl; for(int k=0;k<G->arcnum;k++) { cin>>v1>>v2>>w; int i = LocateVex(G,v1); int j = LocateVex(G,v2); Arc = new ArcNode; //新建边 Arc->adjvex = j; Arc->weight = w; Arc->next = G->vertices[i].firstArc; G->vertices[i].firstArc = Arc; } } //求各顶点的入度(遍历整个邻接表) void FindIndegree(ALGraph *G,int indegree[MAX]) { int i; ArcNode *p; //初始化每个顶点的入度为0 for(i=0;i<G->vexnum;i++) indegree[i] = 0; for(i=0;i<G->vexnum;i++) { p = G->vertices[i].firstArc; while(p) { indegree[p->adjvex]++; //将每一个临接到的点(终点)自增 p = p->next; } //cout<<i<<"元素的入度为:"<<indegree[i]<<endl; } } //拓扑排序 int TopoSort(ALGraph *G,stack<int> &T) //T为返回逆拓扑序列的栈 { stack<int> s; //设置辅助栈(正拓扑序列栈) ArcNode *p; int i,k; int indegree[MAX]; //各顶点的入度数组 FindIndegree(G,indegree); for(i=0;i<G->vexnum;i++) { //将入度为0的顶点入栈 if(indegree[i]==0) s.push(i); } for(i=0;i<G->vexnum;i++) ve[i] = 0; //初始化最早发生时间 int count = 0; while(!s.empty()) { i = s.top(); s.pop(); //将栈顶从S栈出栈 T.push(i); //将i节点进入T栈,形成逆拓扑序列 count++; //统计已输出的顶点数 p = G->vertices[i].firstArc; while(p!=NULL) { k = p->adjvex; indegree[k]--; //i号顶点已出栈,所以将i号顶点的每个邻接点的入度自减 if(indegree[k]==0) s.push(k); //如果入度减为0,则入栈 if(ve[i]+p->weight>ve[k]) ve[k] = ve[i]+p->weight; //按拓扑顺序更新事件的最早发生事件 p = p->next; } } if(count<G->vexnum) return -1; //存在回路 else return 0; } //求关键路径(AOE网,边表示活动的网) int CriticalPath(ALGraph *G) { int i,j,k; int dut,ei,li; int vl[MAX]; //每个事件的最晚发生事件 ArcNode *p; stack<int> T; if(TopoSort(G,T)) //求事件的最早发生时间和逆拓扑序列 return -1; for(i=0;i<G->vexnum;i++) vl[i] = ve[G->vexnum-1]; //将各事件的最迟发生事件初始化为汇点的最早发生时间 while(!T.empty()) //按逆拓扑序列求各事件的最晚发生时间 { j = T.top(); T.pop(); p = G->vertices[j].firstArc; while(p!=NULL) //遍历整个栈 { k = p->adjvex; dut = p->weight; if(vl[k]-dut<vl[j]) vl[j] = vl[k]-dut; p = p->next; } } cout<<"关键活动的相关信息如下:"<<endl; cout<<"活动"<<setw(16)<<"最早发生时间"<<setw(16)<<"最晚发生时间"<<setw(10)<<"持续时间"<<endl; for(j =0;j<G->vexnum;j++) //扫描每一条弧,求出e(i),l(i),找出关键路径 { p = G->vertices[j].firstArc; while(p) { k = p->adjvex; dut = p->weight; ei = ve[j]; //活动的最早发生时间 li = vl[k]-dut; //活动的最晚发生时间 if(ei==li) //输出关键活动的相关信息(ei,li,dut) { cout<<"("<<G->vertices[j].data<<","<<G->vertices[k].data<<")"<<setw(10)<<ei <<setw(14)<<li<<setw(14)<<dut<<endl; } p = p->next; } } return 0; } /* a b c d e f g h i a b 6 a c 4 a d 5 b e 1 c e 1 d f 2 e g 9 b h 7 f h 4 g i 2 h i 4 */
原文地址:http://blog.csdn.net/huolang_vip/article/details/46564793