拓扑排序和关键路径

来源:互联网 发布:刷排名龙卷风优化软件 编辑:程序博客网 时间:2024/05/16 18:06


 

拓扑排序:

       每次选择前驱节点为0的节点,然后删除以其为顶点的边,重复上述操作,直到删除所有节点为止或者所有节点都有前驱.若还有剩余节点,那么图存在环.

关键路径(图中最长的路径):

活动:图中的弧.

事件:图中的顶点.

由于活动时间长短可能不同,导致事件发生的时间可以不同,v1vi的最长路径长度是节点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
原创粉丝点击