【东华大学oj】获取AOE网的关键路径

获取AOE网的关键路径

作者: 冯向阳

时间限制: 1s

章节: 课程设计

问题描述

建立一个有向网AOE网,设计并完成一算法Get_CriticalPath(),获取关键路径。该路径仅输出,不须保存。

提示:在AOE网中,

(1)关键活动:开始时间余量为0的活动。即活动的最早开始时间等于它的最迟开始时间。 

(2)根据各个顶点的Ve和Vl值,在求得每条弧s的最早开始时间e[s]和最迟开始时间l[s]后,若某条弧满足条件e[s]=l[s],该弧所对应的活动即为关键活动。

(3)关键路径:由关键活动所形成的从源点到汇点的每一条路径(注意:关键路径可能有多条)。

参考函数原型:

//获取AOE网各顶点事件的最早发生时间ve和最迟发生时间vl、活动ak的最早开始时间e和最迟开始时间l、一条关键路径

template<class TypeOfVer, class TypeOfEdge>

bool adjlist_graph<TypeOfVer, TypeOfEdge>::Get_CriticalPath(int ve[], int vl[]);

输入说明

第一行:图的类型

第二行:结点数

第三行:结点集

第四行:边数

第五行:边集

第六行:权集

输出说明

第一行:顶点集

第二行:邻接表

空行

顶点i Ve[i] Vl[i](列与列之间用格式控制符'\t'分隔)

...

空行

<弧尾,弧头> e[k] l[k](列与列之间用格式控制符'\t'分隔)

...

空行

<弧尾,弧头>-><弧尾,弧头>...

#include <iostream>
#include <string>
#include <vector>
#include <queue>
#include<tuple>
using namespace std;

template<class TypeOfEdge>
struct edgeNode
{
    int end;
    TypeOfEdge weight;
    edgeNode<TypeOfEdge>* next;

    edgeNode(const int& e, const TypeOfEdge& w, edgeNode<TypeOfEdge>* ptr = nullptr)
    {
        end = e;
        weight = w;
        next = ptr;
    }
};

template<class TypeOfVer, class TypeOfEdge>
struct verNode
{
    TypeOfVer ver;
    edgeNode<TypeOfEdge>* head;

    verNode(edgeNode<TypeOfEdge>* h = nullptr)
    {
        head = h;
    }
};

template <class TypeOfVer, class TypeOfEdge>
class adjlist_graph
{
private:
    int Vers; // Number of vertices
    int Edges; // Number of edges
    verNode<TypeOfVer, TypeOfEdge>* verList;
    string GraphKind;

public:
    adjlist_graph(const string& kd, int vSize, const TypeOfVer d[]) : Vers(vSize), GraphKind(kd)
    {
        verList = new verNode<TypeOfVer, TypeOfEdge>[Vers];
        for (int i = 0; i < Vers; ++i)
        {
            verList[i].ver = d[i];
        }
    }

    adjlist_graph(const string& kd, int vSize, int eSize, const TypeOfVer d[], int** e) : Vers(vSize), GraphKind(kd)
    {
        verList = new verNode<TypeOfVer, TypeOfEdge>[Vers];
        for (int i = 0; i < Vers; ++i)
        {
            verList[i].ver = d[i];
            verList[i].head = nullptr;
        }

        for (int i = 0; i < eSize; ++i)
        {
            int u = e[i][0];
            int v = e[i][1];
            edgeNode<TypeOfEdge>* newNode = new edgeNode<TypeOfEdge>(v, 0, verList[u].head);
            verList[u].head = newNode;

            newNode = new edgeNode<TypeOfEdge>(u, 0, verList[v].head);
            verList[v].head = newNode;
        }
    }

    adjlist_graph(const string& kd, int vSize, int eSize, const TypeOfVer d[], int** e, const TypeOfEdge w[]) : Vers(vSize), GraphKind(kd)
    {
        verList = new verNode<TypeOfVer, TypeOfEdge>[Vers];
        for (int i = 0; i < Vers; ++i)
        {
            verList[i].ver = d[i];
            verList[i].head = nullptr;
        }

        for (int k = 0; k < eSize; ++k)
        {
            int u = e[k][0];
            int v = e[k][1];
            TypeOfEdge weight = w[k];

            if (GraphKind == "DG" || GraphKind == "DN")
            {
                edgeNode<TypeOfEdge>* newNode = new edgeNode<TypeOfEdge>(v, weight, verList[u].head);
                verList[u].head = newNode;
            }
            else
            {
                edgeNode<TypeOfEdge>* newNode = new edgeNode<TypeOfEdge>(v, weight, verList[u].head);
                verList[u].head = newNode;

                newNode = new edgeNode<TypeOfEdge>(u, weight, verList[v].head);
                verList[v].head = newNode;
            }
        }
    }

    ~adjlist_graph()
    {
        for (int i = 0; i < Vers; ++i)
        {
            edgeNode<TypeOfEdge>* curr = verList[i].head;
            while (curr != nullptr)
            {
                edgeNode<TypeOfEdge>* temp = curr;
                curr = curr->next;
                delete temp;
            }
        }
        delete[] verList;
    }

    void printAdjList()
    {
        for (int i = 0; i < Vers; ++i)
        {
            cout << verList[i].ver;
            edgeNode<TypeOfEdge>* curr = verList[i].head;
            while (curr != nullptr)
            {
                cout << "->" << curr->end << "(" << curr->weight << ")";
                curr = curr->next;
            }
            cout << endl;
        }
    }

    bool PrintMatrix()
    {
        for (int i = 0; i < Vers; ++i)
        {
            cout << verList[i].ver;
            if (i != Vers - 1)
                cout << " ";
        }
        cout << endl;
        return true;
    }

    bool Get_CriticalPath(int ve[], int vl[]);


    void printVeVl(int ve[], int vl[])
    {
        std::vector<std::tuple<TypeOfVer, TypeOfVer, int, int>> edgeInfo; // Store (u, v, e[k], l[k])

        for (int i = 0; i < Vers; ++i)
        {
            edgeNode<TypeOfEdge>* curr = verList[i].head;
            while (curr != nullptr)
            {
                int u = i; // Tail
                int v = curr->end; // Head
                int ek = ve[u];
                int lk = vl[v] - curr->weight;
                edgeInfo.emplace_back(verList[u].ver, verList[v].ver, ek, lk);
                curr = curr->next;
            }
        }

        for (const auto& edge : edgeInfo)
        {
            // 使用结构化绑定解构tuple
            auto [u, v, ek, lk] = edge;
            std::cout << "<" << u << ","<< v << ">"<<"\t"<< ek ;
            cout<<"\t"<< lk << std::endl;
        }
    }

    void insert(TypeOfVer x, TypeOfVer y, TypeOfEdge w);

    bool topological_sort(vector<int>& topoOrder);

    void printVertexVeVl(int ve[], int vl[]);
};

template<class TypeOfVer, class TypeOfEdge>
void adjlist_graph<TypeOfVer, TypeOfEdge>::insert(TypeOfVer x, TypeOfVer y, TypeOfEdge w)
{
    int u = -1, v = -1;
    for (int i = 0; i < Vers; ++i)
    {
        if (verList[i].ver == x) u = i;
        if (verList[i].ver == y) v = i;
    }
    if (u != -1 && v != -1)
    {
        verList[u].head = new edgeNode<TypeOfEdge>(v, w, verList[u].head);
        ++Edges;
    }
}

template<class TypeOfVer, class TypeOfEdge>
bool adjlist_graph<TypeOfVer, TypeOfEdge>::topological_sort(std::vector<int>& topoOrder)
{
    std::vector<int> inDegree(Vers, 0);
    for (int i = 0; i < Vers; ++i)
    {
        for (edgeNode<TypeOfEdge>* p = verList[i].head; p != nullptr; p = p->next)
        {
            ++inDegree[p->end];
        }
    }

    std::queue<int> q;
    for (int i = 0; i < Vers; ++i)
    {
        if (inDegree[i] == 0) q.push(i);
    }

    while (!q.empty())
    {
        int u = q.front();
        q.pop();
        topoOrder.push_back(u);
        for (edgeNode<TypeOfEdge>* p = verList[u].head; p != nullptr; p = p->next)
        {
            if (--inDegree[p->end] == 0) q.push(p->end);
        }
    }

    return (topoOrder.size() == Vers);
}


template<class TypeOfVer, class TypeOfEdge>
void adjlist_graph<TypeOfVer, TypeOfEdge>::printVertexVeVl(int ve[], int vl[])
{
    for (int i = 0; i < Vers; ++i)
    {
        std::cout << verList[i].ver << "\t" << ve[i] << "\t" << vl[i] << "\n";
    }
}

template<class TypeOfVer, class TypeOfEdge>
bool adjlist_graph<TypeOfVer, TypeOfEdge>::Get_CriticalPath(int ve[], int vl[])
{
    cout << endl;
    std::vector<int> topoOrder;
    if (!topological_sort(topoOrder)) return false;

    // Step 2: Calculate ve[]
    for (int i = 0; i < Vers; ++i) ve[i] = 0;
    for (int i : topoOrder)
    {
        for (edgeNode<TypeOfEdge>* p = verList[i].head; p != nullptr; p = p->next)
        {
            if (ve[p->end] < ve[i] + p->weight) ve[p->end] = ve[i] + p->weight;
        }
    }

    // Step 3: Calculate vl[]
    for (int i = 0; i < Vers; ++i) vl[i] = ve[Vers - 1];
    for (auto it = topoOrder.rbegin(); it != topoOrder.rend(); ++it)
    {
        int i = *it;
        for (edgeNode<TypeOfEdge>* p = verList[i].head; p != nullptr; p = p->next)
        {
            if (vl[i] > vl[p->end] - p->weight) vl[i] = vl[p->end] - p->weight;
        }
    }
    // Print ve and vl
    printVertexVeVl(ve, vl);
    cout << endl;
    printVeVl(ve, vl);
    cout << endl;
    // Step 4: Identify and print the critical path
    std::vector<std::pair<TypeOfVer, TypeOfVer>> path;
    for (int i = 0; i < Vers; ++i)
    {
        for (edgeNode<TypeOfEdge>* p = verList[i].head; p != nullptr; p = p->next)
        {
            int e = ve[i];
            int l = vl[p->end] - p->weight;
            if (e == l)
            {
                path.emplace_back(verList[i].ver, verList[p->end].ver);
            }
        }
    }

    // Print the critical path
    for (size_t i = 0; i < path.size(); ++i)
    {
        std::cout << "(" << path[i].first << "," << path[i].second << ")";
        if (i != path.size() - 1)
        {
            cout << "->";
        }
    }
    std::cout << std::endl;

    return true;
}


int main()
{
    string graphType;
    int n, m;
    cin >> graphType >> n;

    char* verArr = new char[n];
    for (int i = 0; i < n; ++i)
    {
        cin >> verArr[i];
    }

    cin >> m;
    int** edgeArr = new int* [m];
    for (int i = 0; i < m; ++i)
    {
        edgeArr[i] = new int[2];
        cin >> edgeArr[i][0] >> edgeArr[i][1];
    }

    int* weightArr = new int[m];
    for (int i = 0; i < m; ++i)
    {
        cin >> weightArr[i];
    }

    adjlist_graph<char, int> graph(graphType, n, m, verArr, edgeArr, weightArr);
    graph.PrintMatrix();
    graph.printAdjList();

    int* ve = new int[n];
    int* vl = new int[n];
    graph.Get_CriticalPath(ve, vl);

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Juneeeeeeeeeeeee

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值