拓扑排序和关键路径
来源:互联网 发布:刷排名龙卷风优化软件 编辑:程序博客网 时间:2024/05/16 18:06
拓扑排序:
每次选择前驱节点为0的节点,然后删除以其为顶点的边,重复上述操作,直到删除所有节点为止或者所有节点都有前驱.若还有剩余节点,那么图存在环.
关键路径(图中最长的路径):
活动:图中的弧.
事件:图中的顶点.
由于活动时间长短可能不同,导致事件发生的时间可以不同,从v1到vi的最长路径长度是节点i的最早发生时间,不推迟整个工程完成的情况下,事件vi的最迟开始时间.
1.根据拓扑序,更新所有节点的最早发生时间,使其最大.
2.令终点的最迟开始时间等于最早发生时间.
3.根据逆拓扑序,更新所有节点的最迟开始时间,使其最小.
4.如果一个节点的最迟开始时间等于最早发生时间,那么该事件为关键事件,如果一条弧两端的节点都是关键事件,那么该弧为关键活动.这样就可以查找到所有关键活动了.
(1)为什么要根据拓扑序来扩展节点?
因为当拓扑序扩展到某一个节点时候,该节点已经没有前驱了.所以可以到达该节点的路径都已经计算过了,即该节点所记录的路径值为v0到达vi的最大值.
(2)为什么要根据逆拓扑序来计算最迟开始时间?
如果一个图可以进行拓扑排序,那么把该图中所有路径首尾倒置,即箭头方向调转,该图也一定可以进行拓扑排序,且和倒转前的图的拓扑排序恰好相反.这样,我们可以把逆拓扑序看作路径倒转后的拓扑序.这样根据上面的拓扑序扩展原理,此处我们使用逆拓扑序可以令扩展出来的节点的最迟开始时间最小
#include<iostream>#include<deque>#include<stack>#include<queue> usingnamespace std;#defineVexNum 9#defineVEXMAX 100000typedefchar VextexType;typedefint EdgeType; structEdgeNode;structEdgeNode { VextexType HeadName; VextexType TailName; EdgeType weight; EdgeNode *VexOut; EdgeNode *VexIn; }; structvexTopological { char name; int preVexNum; int early; int last; bool isUsed;}vextopo[VexNum]; structvexWeight{ char name; int pathWeight; char path[VexNum+1];}; typedefstruct{ VextexType name; EdgeNode *VexOutlink; EdgeNode *VexInlink;}VexNode; VexNodeadjList[VexNum]; voidcreatGraph(){ VextexType vextemp; EdgeType edgetemp; //char a[]={'A','B','C','D','E'}; char a[]={'A', 'B', 'C', 'D', 'E', 'F','G', 'H', 'I'}; int b[] = { 0, 6, 4, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 7, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0 ,0 ,0, 0, 2, 0, 0, 0, 0 ,0 ,0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0}; //input n vextex for ( int i=0; i<VexNum ; ++i ){ cin>>vextemp; //vextemp = a[i]; adjList[i].name = vextemp; adjList[i].VexOutlink = NULL; adjList[i].VexInlink = NULL; } for ( int i=0; i<VexNum*VexNum; ++i ){ cin>>edgetemp; //edgetemp = b[i]; if ( edgetemp==0 ){ continue; } EdgeNode *pEdge = new EdgeNode; pEdge->HeadName =adjList[i/VexNum].name; pEdge->TailName =adjList[i%VexNum].name; pEdge->weight = edgetemp; pEdge->VexOut = adjList[i/VexNum].VexOutlink; if ( pEdge->VexOut ){ while ( pEdge->VexOut->VexOut){ pEdge->VexOut=pEdge->VexOut->VexOut; } pEdge->VexOut->VexOut =pEdge; pEdge->VexOut=NULL; } else { adjList[i/VexNum].VexOutlink =pEdge; pEdge->VexOut = NULL; } } for ( int i=0 ;i<VexNum ;++i ){ EdgeNode **pInLink =&adjList[i].VexInlink; for ( int j=0; j<VexNum; ++j ){ if ( i==j ){ continue; } EdgeNode *p =adjList[j].VexOutlink; while ( p ){ if ( p->TailName !=adjList[i].name ){ p = p->VexOut; continue; } *pInLink = p; pInLink = &p->VexIn; p = p->VexOut; } } *pInLink = NULL; }} voiddestroyGrape(){ for ( int i=0; i<VexNum ;++i ){ EdgeNode *p = adjList[i].VexOutlink; EdgeNode *q; while ( p ){ q = p; p = p->VexOut; delete q; } } } voidprintGrape(){ for ( int i=0; i<VexNum; ++i ){ cout<<adjList[i].name<<"-->"; EdgeNode *p = adjList[i].VexOutlink; while ( p ){ cout<<"("<<p->HeadName<<","<<p->TailName<<","<<p->weight<<")"; p = p->VexOut; } cout<<endl; p = adjList[i].VexInlink; cout<<adjList[i].name<<"-->"; while ( p ){ cout<<"("<<p->HeadName<<","<<p->TailName<<","<<p->weight<<")"; p = p->VexIn; } cout<<endl; }} voidtopologicRank(){ EdgeNode *pPre; EdgeNode *pNext; vexTopological *ptopo; stack<vexTopological*> s; deque<vexTopological*> sPrint; for ( int i=0; i<VexNum; ++i ){ int vextopoNum = 0; vextopo[i].name = i+'A'; vextopo[i].early = 0; vextopo[i].last = VEXMAX; vextopo[i].isUsed = false; pPre = adjList[i].VexInlink; while ( pPre ){ pPre = pPre->VexIn; vextopoNum++; } vextopo[i].preVexNum = vextopoNum; } //按拓扑顺序压入栈中. for ( int i=0; i<VexNum; ++i ){ int topoNum = 0; while ( topoNum<VexNum && vextopo[topoNum].preVexNum &&vextopo[topoNum].isUsed ){ topoNum ++; } if ( topoNum == VexNum ){ cout<<"hascycle"<<endl; return ; } topoNum = true; s.push(&vextopo[i]); sPrint.push_back(&vextopo[i]); pNext = adjList[i].VexOutlink; while ( pNext ){ int nextNum =pNext->TailName-'A'; if ( vextopo[nextNum].early <(vextopo[i].early + pNext->weight) ){ vextopo[nextNum].early =vextopo[i].early + pNext->weight; } vextopo[nextNum].preVexNum--; pNext = pNext->VexOut; } } ptopo = s.top(); s.pop(); ptopo->last = ptopo->early; s.push(ptopo); while ( !s.empty() ){ int vexPos; int preVexPos; ptopo = s.top(); s.pop(); vexPos = ptopo->name-'A'; pPre = adjList[vexPos].VexInlink; while ( pPre ){ preVexPos = pPre->HeadName-'A'; if ( vextopo[preVexPos].last >ptopo->last - pPre->weight ){ vextopo[preVexPos].last = ptopo->last - pPre->weight; } pPre = pPre->VexIn; } } while ( !sPrint.empty() ){ vexTopological * p = sPrint.front(); sPrint.pop_front(); if ( p->early != p->last ){ continue; } int vexPos = p->name - 'A'; EdgeNode * pedge =adjList[vexPos].VexOutlink; while ( pedge ){ if (vextopo[pedge->TailName-'A'].last == vextopo[pedge->TailName-'A'].early){ cout<<"("<<pedge->HeadName<<","<<pedge->TailName<<","<<pedge->weight<<")"; } pedge = pedge->VexOut; } }} int main(){ creatGraph(); printGrape(); topologicRank(); destroyGrape();}
测试数据:
0 0
- 拓扑排序和关键路径
- 拓扑排序和关键路径
- 拓扑排序和关键路径
- 拓扑排序和关键路径
- 拓扑排序和关键路径
- 拓扑排序和关键路径
- 拓扑排序和关键路径
- 拓扑排序关键路径
- 拓扑排序,关键路径
- 拓扑排序&关键路径
- 拓扑排序--关键路径
- 关键路径 + 拓扑排序
- 图(五)关键路径和拓扑排序
- 图(拓扑排序和关键路径)
- 拓扑排序和关键路径算法实现
- No.3拓扑排序和关键路径
- 拓扑排序与关键路径
- 拓扑排序--关键路径实现
- 巴氏刷牙法
- 单源最短路径
- 雪天驾车安全提示
- PHP如何解决网站大流量与高并发的问题
- 汇编学习日志——add指令
- 拓扑排序和关键路径
- 转录组测序分析中cufflinks的使用及问题
- SAP SMP 3.0 国际化 i18n
- 电脑内存常见问题处理方法
- Lua中实现观察者模式
- AcCmColor类简述
- RAID+LVM技术之三fdisk篇
- VC获取屏幕分辨率及大小相关
- 2013-04-19期-开发前准备工作