• SDUT-2498_AOE网上的关键路径


    数据结构实验之图论十一:AOE网上的关键路径

    Time Limit: 2000 ms Memory Limit: 65536 KiB

    Problem Description

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

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

    Input

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

    Output

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

    Sample Input

    9 11
    1 2 6
    1 3 4
    1 4 5
    2 5 1
    3 5 1
    4 6 2
    5 7 9
    5 8 7
    6 8 4
    8 9 4
    7 9 2

    Sample Output

    18
    1 2
    2 5
    5 7
    7 9

    题解:由于点的数量特别大,所以不能用连接矩阵存图,可以用连接链表或者向前星,这里用的是向前星。
    然后利用SPFA找出最长的路径就可以了。注意反向建图,这样按照字典序输出路径比较好输出。

    #include <string.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
    
    int S,E;/*起点终点*/
    int n;/*n节点数量*/
    int f[10050];/*记录点是否被遍历过*/
    int INF = 1e9+7;/*相当于无穷大*/
    int c[10050],r[10050];/*记录节点的出度,入度*/
    int pre[10050];
    
    struct node
    {
        int to,next,w;
    }s[50050];
    
    int head[10050],num;
    
    void add(int u,int v,int w)
    {
        s[num].to = v;
        s[num].w = w;
        s[num].next = head[u];
        head[u] = num ++;
    }
    
    void show(int x)
    {
        if(pre[x]==-1)
            return;
        printf("%d %d
    ",x,pre[x]);
        show(pre[x]);
    }
    
    void SPFA()
    {
        int i,u,v,w;
        int dis[10050];
        int q[10050],fr,ba;
        for(i=1;i<=n;i++)
        {
            dis[i] = -1;
            f[i] = 0;
        }
        dis[S] = 0;
        f[S] = 1;
        fr = ba = 0;
        q[ba++] = S;
        while(fr!=ba)
        {
            u = q[fr++];
            f[u] = 0;
            for(i=head[u];i!=-1;i=s[i].next)
            {
                v = s[i].to;
                w = s[i].w;
                if(dis[u]+w>dis[v]||(dis[u]+w==dis[v]&&pre[v]>u))
                {
                    dis[v] = dis[u] + w;
                    pre[v] = u;
                    if(!f[v])
                    {
                        f[v] = 1;
                        q[ba++] = v;
                    }
                }
            }
        }
        printf("%d
    ",dis[E]);
        show(E);
    }
    
    int main()
    {
        int m,i;
        while(scanf("%d%d",&n,&m)!=EOF)
        {
            num = 0;
            for(i=1;i<=n;i++)
            {
                head[i] = -1;
                c[i] = r[i] = 0;
                pre[i] = -1;
            }
            for(i=0;i<m;i++)
            {
                int a,b,w;
                scanf("%d%d%d",&a,&b,&w);
                add(b,a,w);
                c[b]++;
                r[a]++;
            }
            for(i=1;i<=n;i++)
            {
                if(c[i]==0)
                    E = i;
                if(r[i]==0)
                    S = i;
            }
            SPFA();
        }
        return 0;
    }
    
  • 相关阅读:
    UINavigationController详细(转)
    IOS控件大全及控件大小
    IOS的各种控件(转载,防止遗忘)
    算法导论学习-heapsort
    POJ1502: MPI Maelstrom
    POJ1163 The Triangle: 倒三角形问题
    算法导论学习-Dynamic Programming
    POJ2299: Ultra-QuickSort-合并排序解决逆序数问题
    POJ3750: 小孩报数问题+一道经典约瑟夫问题(猴子选大王)
    用头插法实现单链表整表创建
  • 原文地址:https://www.cnblogs.com/luoxiaoyi/p/10067626.html
Copyright © 2020-2023  润新知