TopSort(拓扑排序)、求关键路径

时间:2023-02-02 14:48:23

程序小白,希望和大家多交流,共同学习

//TopSort拓扑排序
#include<iostream>
#include<string>
#include<queue>
#define MAX_VN 50
#define INF 32767
using namespace std;
typedef string VertexData;

struct ArcNode{
    int adjvex;
    int weight;
    ArcNode *nextArc;
};

struct Vertex{
    VertexData data;
    ArcNode *firstArc;
};

struct AdjList{
    Vertex vertex[MAX_VN];
    int verNum, arcNum;
};
void createAdjList(AdjList &G);
int locateVertex(AdjList &G, VertexData data);
void outputAdjList(AdjList &G);

void topOrder(const AdjList &G,int *order);
void printTopOder(const AdjList &G,int *order);
//关键路径
void criticalPath(const AdjList &G);
int main(){
/* 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 */
    AdjList G;
    createAdjList(G);
    outputAdjList(G);
    cout << "TopOrder:" << endl;
    int *order = new int[G.verNum + 1];
    topOrder(G, order);
    printTopOder(G, order);
    criticalPath(G);
    return 0;
}

void createAdjList(AdjList &G){
    cout << "输入顶点个数和弧的条数:";
    cin >> G.verNum >> G.arcNum;
    cout << "输入顶点信息:";
    for (int i =1; i <= G.verNum; i++){
        cin >> G.vertex[i].data;
        G.vertex[i].firstArc = NULL;//初始化
    }
    cout << "输入各条弧的信息:";
    VertexData u, v;
    int w;
    int i, j;
    for (int k = 1; k <= G.arcNum; k++){
        cin >> u >> v >> w;
        i = locateVertex(G, u);
        j = locateVertex(G, v);

        ArcNode *p = new ArcNode;
        p -> weight = w;
        p -> adjvex = j;
        p -> nextArc = G.vertex[i].firstArc;
        G.vertex[i].firstArc = p;
    }
}
int locateVertex(AdjList &G, VertexData data){
    for (int i = 1; i <= G.verNum; i++){
        if (G.vertex[i].data == data){
            return i;
        }
    }
    return -1;
}
void outputAdjList(AdjList &G){
    for (int i = 1; i <= G.verNum; i++){
        cout << i << " ";
        cout << G.vertex[i].data << " -> ";
        ArcNode *p = G.vertex[i].firstArc;
        while (p){
            cout << p -> adjvex << " " << p -> weight << " -> ";
            p = p -> nextArc;
        }
        cout << " ^" << endl;
    }
}

void topOrder(const AdjList &G, int *order){
    //初始化入度为零
    int *inDegrees = new int[G.verNum + 1];
    for (int i = 1; i <= G.verNum; i++){
        inDegrees[i] = 0;
    }
    //按照G的结构更新度
    ArcNode *p;
    for (int i = 1; i <= G.verNum; i++){
        p = G.vertex[i].firstArc;
        while (p){
            int j = p -> adjvex;
            inDegrees[j]++;
            p = p -> nextArc;
        }
    }
    //将度为0的加入队列
    queue<int> q;
    for (int i = 1; i <= G.verNum; i++){
        if (inDegrees[i] == 0){
            q.push(i);
        }
    }
    //按照出队列的方式,将度为0的入栈,并将此顶点的邻接点的度减一
    //根据出栈顺序,将每次出栈的顶点记录在order中
    int k = 0;
    while (k < G.verNum){
        int z = q.front();
        q.pop();//返回栈顶元素之后要出栈
        order[++k] = z;
        p = G.vertex[z].firstArc;
        while (p){
            int j = p -> adjvex;
            inDegrees[j]--;
            if (inDegrees[j] == 0){
                q.push(j);
            }
            p = p -> nextArc;
        }
    }
    delete []inDegrees;
}

void printTopOder(const AdjList &G, int *order){
    for (int i = 1; i <= G.verNum; i++){
        cout << G.vertex[order[i]].data << " ";
    }
    cout << endl;
}
void criticalPath(const AdjList &G){
    int n = G.verNum;
    int *ve = new int[n + 1];
    int *vl = new int[n + 1];
    int *order = new int[n + 1];
    topOrder(G, order);

    for (int i = 1; i <= n; i++){
        cout << G.vertex[order[i]].data << " ";
    }
    cout << endl;
    //ve
    for (int i = 1; i <= n; i++){
        ve[i] = 0;
    }
    for (int i = 1; i <= n; i++){
        int u = order[i];
        ArcNode *p = G.vertex[u].firstArc;
        while (p){
            int j = p -> adjvex;
            if (ve[j] < ve[u] + p -> weight){
                ve[j] = ve[u] + p -> weight;
            }
            p = p -> nextArc;
        }
    }
    for (int i = 1; i <= n; i++){
        printf("%-3d", ve[i]);
    }
    cout << endl;

    //vl
    for (int i = 1; i <= n; i++){
        vl[i] = ve[n];
    }
    for (int i = n - 1; i >= 1; i--){
        int u = order[i];
        ArcNode *p = G.vertex[u].firstArc;
        while (p){
            int j = p -> adjvex;
            if (vl[u] > vl[j] - p -> weight){
                vl[u] = vl[j] - p -> weight;
            }
            p = p -> nextArc;
        }
    }
    for (int i = 1; i <= n; i++){
        printf("%-3d", vl[i]);
    }
    cout << endl;

    //关键路径
//其实ve和vl都是在存储关键路径,最大ve是加法,加的最多所以最大,那么加的最多的是关键路径
//最小vl是减法,减的最多所以最小,那么减的最多的是关键路径
    cout << "关键路径是:";
    int ee, el;
    for (int i = 1; i < n; i++){
        int u = order[i];
        ee = ve[u];
        ArcNode *p = G.vertex[u].firstArc;
        while (p){
            int j = p -> adjvex;
            el = vl[j] - p -> weight;
            if (ee == el){
                cout << G.vertex[u].data << " -> " << G.vertex[j].data << endl;
            }
             p = p -> nextArc;
        }
    }
    delete []ve;
    delete []vl;
    delete []order;
}