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

数据结构实验之图论十一:AOE网上的关键路径
Time Limit: 2000 ms Memory Limit: 65536 KiB
Submit Statistic
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

#include <bits/stdc++.h>

using namespace std;

class Edge
{
public:
    int from,to, data;
    Edge(int x=0,int y=0,int z=0) : from(x), to(y), data(z) {}
};

class Vertex
{
public:
    int id;
    int ans;  // 节点入度
    vector<int >next;
};

class Map
{
private:
    int n;
    bool visit[10000+10] ;
    vector<Edge> E;
    vector<int> p; // 存放拓扑排序序列
    int ve[10000+10];// 顶点活动发生的最早发生时间
    int vl[10000+10];// 定点活动发生的最晚时间
public:
    Vertex G[10000+10];
    
    void Init(int n)
    {
        this->n = n;
        E.clear();
        p.clear();
        for(int i = 0 ; i<= n; i++)
        {
            ve[i] = - 1 ;
            vl[i] = INT_MAX;
            visit[i] = false;
            G[i].ans = 0 ;
            G[i].next.clear();
            G[i].id = i;
        }
    }
    
    void Add_Edge(int x,int y,int z=0)
    {
        E.push_back(Edge(x,y,z));
        int len = E.size();
        G[x].next.push_back(len - 1 ) ;
        G[y].ans++;
    }
    bool TopSort()
    {
        queue<int> L;
        for(int i = 1; i<=n ; i++) // 将入度为零的点进栈
        {
            if(G[i].ans == 0)
            {
                L.push(G[i].id);
            }
        }
        while(!L.empty())
        {
            int t = L.front();
            L.pop();
            p.push_back(t);
            visit[t] = true;
            int len = G[t].next.size();
            for(int i = 0 ; i<len; i++ )  // 删边
            {
                int j =E[G[t].next[i]].to;
                int data = E[G[t].next[i]].data;
                if(visit[j] == false)
                {
                    G[j].ans--;
                    if(G[j].ans == 0)
                    {
                        L.push(j) ;
                    }
                }
            }
        }
        if(p.size() == n)
        {
            return true;
        }
        return false;
    }
    
    void BFS(int x,int y)// 利用BFS求得 每个定点的最早开始时间 以及最晚时间
    {
        ve[x] = 0 ;
        memset(visit,false, sizeof(visit)) ;
        queue<int>L;
        stack<Edge> l;// 利 栈 保存边的相对位置
        L.push(x);
        
        while(!L.empty())
        {
            int t = L.front() ;
            L.pop();
            if(visit[t]== true)
                continue;
            visit[t] = true;
            int len = G[t].next.size();
            for(int i = 0 ; i<len; i++)
            {
                l.push(E[G[t].next[i]]) ;
                int to   = E[G[t].next[i]].to;
                int data = E[G[t].next[i]].data;
                ve[to] = max(ve[to],ve[t] + data);
                L.push(to);
            }
        }
        vl[y] =  ve[y];
        while(!l.empty())
        {
            Edge t  = l.top();
            l.pop();
            int from = t.from;
            int to   = t.to;
            int data = t.data;
            vl[from] = min(vl[from],vl[to]-data);
        }
    }
    
    void CriticalPath(int x,int y)
    {
        memset(visit,false,sizeof(visit)) ;
        BFS(x,y);

        p.clear() ;
        p.push_back(x) ;
        int sum = 0 ;

        queue<int > L;
        L.push(x) ;
        memset(visit,false,sizeof(visit)) ;
        while(!L.empty())
        {
            int t = L.front() ;
            L.pop();
            if(visit[t] == true)
            {
                continue;
            }
            visit[t] = true;
            int len = G[t].next.size();
            int key = INT_MAX;
            bool flag = false;
            int data = -1 ;
            for(int i = 0 ; i<len; i++)
            {
                int to   = E[G[t].next[i]].to;
                int ans  = E[G[t].next[i]].data;
                int from = E[G[t].next[i]].from ;

                int x = ve[from] , y = vl[to] - ans;

                if(x == y)
                {

                    if(key > to)
                    {
                        key = to ;
                        data = ans;
                    }
                    flag = true;
                }
            }
            if(flag == true)
            {

                sum += data;
                L.push(key) ;
                p.push_back(key) ;
                t = key;
            }
        }
        cout<<sum<<endl;
        int len = p.size();
        for(int i = 0 ; i<len-1; i++)
        {
            cout<<p[i]<<" "<<p[i+1]<<endl;
        }
    }
};

Map a;
bool b[10000+10] = {false}; // 源点
bool c[10000+10] = {false}; // 汇点
int main()
{
    int n,m;
    while(cin>>n>>m)
    {
        a.Init(n);
        memset(b,false,sizeof(b)) ;
        memset(c,false,sizeof(c)) ;
        for(int i = 0 ; i<m; i++)
        {
            int x,y,z;
            cin>>x>>y>>z;
            a.Add_Edge(x,y,z) ;
            b[x] = true;
            c[y] = true;
        }
        int x, y ;
        for(int i = 1 ; i<= n; i++)
        {
            if(b[i] == false)
            {
                y = i;
            }
            if(c[i] == false)
            {
                x = i;
            }
        }
        a.CriticalPath(x,y);
    }
    return 0 ;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值