AOE关键路径

来源:互联网 发布:关于网络直播的作文800 编辑:程序博客网 时间:2024/05/29 03:03

AOE网上的关键路径

Time Limit: 1000ms   Memory limit: 65536K  有疑问?点这里^_^

题目描述

    一个无环的有向图称为无环图(Directed Acyclic Graph),简称DAG图。 
   
 AOE(Activity On Edge)网:顾名思义,用边表示活动的网,当然它也是DAG。与AOV不同,活动都表示在了边上,如下图所示:
                                     

    
如上所示,共有11项活动(11条边),9个事件(9个顶点)。整个工程只有一个开始点和一个完成点。即只有一个入度为零的点(源点)和只有一个出度为零的点(汇点)。
    
关键路径:是从开始点到完成点的最长路径的长度。路径的长度是边上活动耗费的时间。如上图所示,到 579是关键路径(关键路径不止一条,请输出字典序最小的),权值的和为18

输入

    这里有多组数据,保证不超过10组,保证只有一个源点和汇点。输入一个顶点数n(2<=n<=10000),边数m(1<=m <=50000),接下来m行,输入起点sv,终点ev,权值w1<=sv,ev<=n,sv != ev,1<=w <=20)。数据保证图连通。

输出

    关键路径的权值和,并且从源点输出关键路径上的路径(如果有多条,请输出字典序最小的)。

示例输入

9 111 2 61 3 41 4 52 5 13 5 14 6 25 7 95 8 76 8 48 9 47 9 2

示例输出

181 22 55 77 9


/*    边-->活动  点-->事件*/# include <bits/stdc++.h># define MAXN 10010 //最大顶点数# define MAXM 50010 //最大边数using namespace std;struct node{    int d; //<u,v>之间的距离    int to; //v点    int on;//活动序号    struct node*next;};typedef struct node Node;struct node *ls1[MAXN]; //正向存储图的信息,出边表的表头struct node *ls2[MAXN]; //逆向存储图的信息,入边表的表头int Ee[MAXN]; //各事件最早可能开始的时间int El[MAXN];//各事件的最迟允许开始时间int e[MAXN]; //各活动最早可能开始的时间等于Eeint l[MAXN]; //各活动的最迟允许开始时间int cnt1[MAXN];//统计正向的各个点的入度int cnt2[MAXN];//统计反向的各个点的出度int n,m; //n 顶点数 m 边数void O_TopSort() //正向拓扑求Ee,可以认为是单点求最长路径{    int i,u,v;    Node*p;    memset(Ee,0,sizeof(Ee));    stack<int>s;    for(i=1;i<=n;i++)    {        if(cnt1[i] == 0)//入度为0的点入栈            s.push(i);    }    while(!s.empty())    {        u = s.top();        s.pop();        p = ls1[u]; //找到从u发出的每条边,将终点v度数减去1        while(p)        {            v = p->to;            cnt1[v]--;            if(cnt1[v] == 0)                s.push(v);            if(Ee[u] + p->d > Ee[v])                Ee[v] = Ee[u] + p->d;            p = p->next;        }    }}void R_TopSort() //逆序拓扑{    int i,u,v;    Node*p;    memset(El,0,sizeof(El));    stack<int> s;    for(i=1;i<=n;i++)    {        El[i] = Ee[n];        if(cnt2[i] == 0)            s.push(i);    }    while(!s.empty())    {        u = s.top();        s.pop();        p = ls2[u];        while(p)        {            v = p->to;            if(--cnt2[v] == 0)                s.push(v);            if(El[u] - p->d < El[v])                El[v] = El[u] - p->d;            p = p->next;        }    }}int main(){    int i,u,v,w;    Node*p;    Node*q;    while(cin>>n>>m)    {        memset(cnt1,0,sizeof(cnt1));        memset(cnt2,0,sizeof(cnt2));        for(i=1;i<=n;i++)        {            ls1[i] = NULL;            ls2[i] = NULL;        }        for(i=0;i<m;i++)//输入m条边的信息        {            cin>>u>>v>>w;            /*出边表*/            p = new Node;            p->d = w;            p->to = v;            p->on = i;            cnt1[v]++;            p->next = ls1[u];            ls1[u] = p;            /*入边表*/            q = new Node;            q->d = w;            q->to = u;            q->on = i;            cnt2[u]++;            q->next = ls2[v];            ls2[v] = q;        }        O_TopSort();//源点到汇点的最长距离        cout<<Ee[n]<<endl;        R_TopSort();        int k,j;        int Min;        int flag;        for(i=1;i<=n;i++)        {            p = ls1[i];            flag = 0;            if(p)                Min = p->to;            while(p)            {                j = p->to;                k = p->on;//取出改点编号                e[k] = Ee[i]; //边<i,j>                l[k] = El[j] - p->d;                if(e[k] == l[k])//为关键活动                {                    if(Min > j)                    {                        Min = j;                    }                    flag = 1;                }                p = p->next;            }            if(flag)            {                cout<<i<<" "<<Min<<endl;                i = Min - 1;//直接跳转到当前关键路径节点的下一节点                ls1[i] = NULL;//将字典序最小的赋值            }        }    }    return 0;}


0 0