关键路径算法

74 阅读2分钟
#include <iostream>
#include <string.h>
#include <stack>
#include <cstdio>
using namespace std;
typedef string element;
struct ArcNode
{ //边结点
    int weight;
    int adjuex;
    ArcNode *nextarc;
};
struct VNode
{ //顶点结点
    element data;
    ArcNode *firstarc;
};

class Graph
{
private:
    VNode *vertex;
    int vernum, arcnum;

public:
    Graph(int vernum, int arcnum)
    {
        this->vernum = vernum;
        this->arcnum = arcnum;
        vertex = new VNode[vernum];
        for (int i = 0; i < vernum; i++)
        {
            vertex[i].firstarc = NULL;
        }
    }
    int connected(element e)
    {
        for (int i = 0; i < vernum; i++)
        {
            if (e == vertex[i].data)
            {
                return i;
            }
        }
        cout << "没有该顶点" << endl;
        return -1;
    }
    void cinCreate()
    {
        cout << "输入" << vernum << "个顶点" << endl;
        for (int i = 0; i < vernum; i++)
        {
            cin >> vertex[i].data;
        }
        cout << "输入" << arcnum << "条边" << endl;
        element v1, v2;
        int n1, n2;
        for (int i = 0; i < arcnum; i++)
        {
            cin >> v1 >> v2;
            n1 = connected(v1);
            n2 = connected(v2);
            ArcNode *p = new ArcNode;
            p->adjuex = n2;
            cin >> p->weight;
            p->nextarc = vertex[n1].firstarc;
            vertex[n1].firstarc = p;
        }
    }
    void show()
    {
        for (int i = 0; i < vernum; i++)
        {
            ArcNode *p = vertex[i].firstarc;
            while (p)
            {
                cout << "<" << vertex[i].data << ", " << vertex[p->adjuex].data << ">"
                     << " : " << p->weight << endl;
                p = p->nextarc;
            }
        }
    }
    void topoSort(int *arr)
    {
        stack<int> s;
        int i;
        //初始化indegree数组
        int *indegree = new int[vernum];
        for (int i = 0; i < vernum; i++)
        {
            indegree[i] = 0;
        }
        for (i = 0; i < vernum; i++)
        {
            ArcNode *p = vertex[i].firstarc;
            while (p)
            {
                indegree[p->adjuex]++;
                p = p->nextarc;
            }
        }
        //入度为0的点入栈
        for (i = 0; i < vernum; i++)
        {
            if (!indegree[i])
            {
                s.push(i);
            }
        }
        //其他为0点入栈
        for (i = 0; i < vernum; i++)
        {
            arr[i] = s.top();
            s.pop();
            ArcNode *p = vertex[arr[i]].firstarc;
            while (p)
            {
                if (!--indegree[p->adjuex])
                {
                    s.push(p->adjuex);
                }
                p = p->nextarc;
            }
        }
    }
    void shortPath()
    {
        int i;
        //调用拓扑排序 排列顺序
        int *topolist = new int[vernum];
        topoSort(topolist);

        //最早发生时间ve
        int *ve = new int[vernum];
        memset(ve, 0, vernum * sizeof(int)); //初始化,int型只能初始化为0或-1
        for (int i = 0; i < vernum; i++)
        {                                    //遍历所有结点
            int k = topolist[i];             //依次取出拓扑序列
            ArcNode *p = vertex[k].firstarc; // p指向k的邻接点
            while (p)
            {                      //邻接点存在
                int j = p->adjuex; //邻接点的位置(下标)
                //在所有最早的时间中找到一个最迟的,(等待最迟的完成)代表该点的最早
                if (ve[j] < ve[k] + p->weight)
                {                              //若k的最早时间 加 k到j 的时间 比j 的最早时间迟,存上最长时间(因为j点要等待它前面所有点完成,即时间最长的完成)
                    ve[j] = ve[k] + p->weight; // ve[j]存上最早时间
                }
                p = p->nextarc;
            }
        }

        //最晚发生时间vl
        int *vl = new int[vernum];
        for (i = 0; i < vernum; i++)
        { //初始化为汇点的最早时间
            vl[i] = ve[vernum - 1];
        }
        for (i = vernum - 1; i >= 0; i--)
        {
            int k = topolist[i];
            ArcNode *p = vertex[k].firstarc;
            while (p)
            {
                int j = p->adjuex; //邻接点
                if (vl[k] > vl[j] - p->weight)
                { //若j最迟时间 减 k到j的时间 比 k的最迟时间早,存最早(在所有最迟时间中找到一个最早的作为最迟时间,以保证所有的都不会迟到)
                    vl[k] = vl[j] - p->weight;
                }
                p = p->nextarc;
            }
        }

        //判断某活动是否为关键活动
        for (i = 0; i < vernum; i++)
        {
            ArcNode *p = vertex[i].firstarc;
            while (p)
            {
                int j = p->adjuex;         //邻接点
                int e = ve[i];             //最早活动
                int l = vl[j] - p->weight; //(最迟活动)邻接点最迟时间 减 i到j的时间
                if (e == l)
                { //相等则为关键路径
                    cout << "<" << vertex[i].data << ", " << vertex[j].data << ">" << ends;
                }
                p = p->nextarc;
            }
        }
        cout << endl;
    }
};

int main()
{
    int n, e;
    freopen("input.txt", "r", stdin);
    cin >> n >> e;
    Graph g(n, e);
    g.cinCreate();
    g.show();
    g.shortPath();

    return 0;
}



input.txt

9 11
v0 v1 v2 v3 v4 v5 v6 v7 v8
v0 v1 6  
v0 v2 4  
v0 v3 5  
v1 v4 1  
v2 v4 1  
v3 v5 2  
v4 v6 9  
v4 v7 7  
v5 v7 4  
v6 v8 2  
v7 v8 4