关键路径算法C++

输入:有向图(顶点序列,有向边序列)

功能要求:能判断是否是AOE 网;输出各关键活动或输出关键路径(包括关键路径的长度)

求AOE中关键路径和关键活动的算法思想:

① 利用拓扑排序求出AOE网的一个拓扑序列;

②  从拓扑排序的序列的第一个顶点(源点)开始,按拓扑顺序依次计算每个事件的最早发生时间ve(i) ;

③  从拓扑排序的序列的最后一个顶点(汇点)开始,按逆拓扑顺序依次计算每个事件的最晚发生时间vl(i) ;          

抽象数据模型

struct node

{

    int v, cost;

    node(int _v, int _cost): v(_v), cost(_cost) {}

};

#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<stack>
#define maxn 1000
using namespace std;
struct node
{
    int v, cost;
    node(int _v, int _cost): v(_v), cost(_cost) {}
};
int ve[maxn];
int vl[maxn];
int n, m;
int indegree[maxn];
vector<node> adj[maxn];
vector<int> path[maxn];
stack<int> s;
int j = 0;  //汇点的编号
bool topologicalsort()
{
    queue<int> q;
    for(int i = 1; i <= n; i++)
    {
        if(indegree[i] == 0)
        {
            q.push(i);
        }
    }
    while(!q.empty())
    {
        int u = q.front();
        q.pop();
        s.push(u);
        for(int i = 0; i < adj[u].size(); i++)
        {
            int v = adj[u][i].v;
            indegree[v]--;
            if(indegree[v] == 0)
            {
                q.push(v);
            }
            if(ve[u] + adj[u][i].cost > ve[v])
            {
                ve[v] = ve[u] + adj[u][i].cost;
            }
        }
    }
    if(s.size() == n) return true;
    else return false;
}
int criticalpath()
{
    fill(ve, ve+maxn, 0);
    if(!topologicalsort()) return -1;
    int maxlength = 0;
    for(int i = 1; i <= n; i++)
    {
        if(ve[i] > maxlength)
        {
            maxlength = ve[i];
            j = i;
        }
    }
    fill(vl, vl+maxn, maxlength);
    while(!s.empty())
    {
        int u = s.top();
        s.pop();
        for(int i = 0; i < adj[u].size(); i++)
        {
            int v = adj[u][i].v;
            if(vl[v] - adj[u][i].cost < vl[u])
            {
                vl[u] = vl[v] - adj[u][i].cost;
            }
        }
    }
    for(int u = 1; u <= n; u++)
    {
        for(int i = 0; i < adj[u].size(); i++)
        {
            int v = adj[u][i].v;
            int cost = adj[u][i].cost;
            int e = ve[u], l = vl[v] - cost;
            if(e == l)
            {
                //printf("%d --> %d\n",u, v);
                path[u].push_back(v);
            }
        }
    }

    return ve[j];
}

vector<int> temppath;
void dfs(int v)
{
    if(v == j)
    {
        temppath.push_back(v);

        for(int i = 0; i < temppath.size() -1; i++)
        {
            printf("%d --> ",temppath[i]);
        }
        printf("%d\n",temppath[temppath.size() -1]);
        temppath.pop_back();

        return;
    }
    temppath.push_back(v);
    for(int i = 0; i < path[v].size(); i++)
    {
        dfs(path[v][i]);
    }
    temppath.pop_back();
}
int main()
{
    printf("请输入顶点数和边数:");
    scanf("%d%d",&n, &m);

    int u1, v1, w1;
    printf("依次输入起点、终点、权值:\n");
    for(int i = 0; i < m; i++)
    {
        scanf("%d%d%d",&u1, &v1, &w1);
        adj[u1].push_back(node(v1, w1));
        indegree[v1]++;
    }
    int ans = criticalpath();
    printf("关键路径长度为:%d\n",ans);
    printf("\n");
    for(int i = 1; i <= n; i++)
    {
        printf("ve[%d] = %d,  vl[%d] = %d\n",i, ve[i], i, vl[i]);
    }
       int vs; //找源点
    for(int i = 1; i <= n; i++)
    {
        if(ve[i] == 0)
        {
            vs = i;
            break;
        }
        else continue;
    }
    printf("\n");
    //printf("关键路径为:\n");
    dfs(vs);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/y0205yang/article/details/130207866