关键路径

纯属儿戏,切莫当真

/*
关键路径
只有一个开始点和一个完成点
*/

#include <iostream>
#include <vector>
using namespace std;

#define MAXSIZE 16
struct BaseNode
{
    BaseNode(){
        tailIndex = 0;
        nWeight = 0;
        tailLink = NULL;    //出
        headIndex = 0;
        headLink = NULL;    //入
    }
    ~BaseNode(){
        while (tailLink)
        {
            BaseNode * t = tailLink;
            tailLink = tailLink->tailLink;
            delete t;
            t = NULL;
        }
        tailLink = NULL;
        while (headLink)
        {
            BaseNode * t = headLink;
            headLink = headLink->headLink;
            delete t;
            t = NULL;
        }
        headLink = NULL;
    }
    int         tailIndex;
    int         nWeight;
    BaseNode *  tailLink;
    int         headIndex;
    BaseNode *  headLink;
};

struct GraphNode
{
    GraphNode(){
        info = '\0';
        firstIn = NULL;
        firstOut = NULL;
    }

    char info;
    BaseNode *firstIn;
    BaseNode *firstOut;
};

class Graph
{
public:
    bool Init(); 

    void FindKeyPath();
public:
    GraphNode m_Node[MAXSIZE];

    int m_VertSize;

    int m_EdgeSize;

};

bool Graph::Init()
{
    cout << "请输入顶点个数" << endl;
    cin >> m_VertSize;
    cout << "请输入顶点信息" << endl;
    for (int i = 1; i <= m_VertSize; i++)
    {
        cin >> m_Node[i].info;
    }
    cout << "请输入边的个数" << endl;
    cin >> m_EdgeSize;
    cout << "请输入边的信息" << endl;
    for (int i = 0; i < m_EdgeSize; i++)
    {
        int nHead, nTail, nWeight;
        cin >> nTail>>nHead  >> nWeight;
        BaseNode *p = new BaseNode;
        p->tailIndex = nTail;
        p->headIndex = nHead;
        /*
            相当于 每次都往头部插 其他节点往后
            类比单链表插入
        */
        p->headLink = m_Node[nHead].firstIn;
        p->tailLink = m_Node[nTail].firstOut;
        p->nWeight = nWeight;
        m_Node[nHead].firstIn = m_Node[nTail].firstOut = p;
    }
    return true;
}

struct KeyInfo
{
    KeyInfo(){
        head = 0;   //弧头 带箭头    终端点
        tail = 0;   //弧尾 没带箭头 初始点
        ee = 0;
        el = 0;
    }
    int head;
    int tail;
    int ee; //最早开始时间
    int el;//最迟开始时间
};
void Graph::FindKeyPath()
{
    int inDegree[MAXSIZE];
    int ve[MAXSIZE];
    int vl[MAXSIZE];
    memset(inDegree, 0, sizeof(inDegree));
    memset(ve, 0, sizeof(ve));
    memset(vl, 0, sizeof(vl));

    vector<KeyInfo> keyInfo;
    vector<int > selectPoint,hasSelectd;

    for (int i = 1; i <= m_VertSize; i++)
    {
        int nSize = 0;
        BaseNode * t = m_Node[i].firstIn;
        while (t)
        {
            nSize++;
            t = t->headLink;
        }
        inDegree[i] = nSize;
    }

    for (int i = 1; i <= m_VertSize; i++)
    {
        if (inDegree[i] == 0)
        {
            selectPoint.push_back(i);
        }
    }

    //ve 最早发生时间
    while (selectPoint.size() > 0)
    {
        int index = selectPoint.front();
        selectPoint.erase(selectPoint.begin());
        hasSelectd.push_back(index);

        BaseNode * t = m_Node[index].firstOut;
        while (t)
        {
            inDegree[t->headIndex]--;
            if (ve[t->headIndex] == 0 || ve[t->headIndex] < t->nWeight + ve[index])
            {
                ve[t->headIndex] = t->nWeight + ve[index];
            }

            KeyInfo m;
            m.head = t->headIndex;
            m.tail = index;
            keyInfo.push_back(m);

            t = t->tailLink;

        }
        for (int i = 1; i <= m_VertSize; i++)
        {
            if (inDegree[i] == 0 && find(hasSelectd.begin(), hasSelectd.end(), i) == hasSelectd.end())
            {
                if (find(selectPoint.begin(), selectPoint.end(), i) == selectPoint.end() )
                    selectPoint.push_back(i);
            }
        }
    }
    vl[m_VertSize] = ve[m_VertSize];

    //vl 最迟发生时间
    vector<int>::reverse_iterator it = hasSelectd.rbegin() ;
    for (; it != hasSelectd.rend(); it++)
    {
        BaseNode * t = m_Node[*it].firstIn;
        while (t)
        {
            if (vl[t->tailIndex] == 0 || vl[t->tailIndex] > vl[*it] - t->nWeight  )
            {
                vl[t->tailIndex] = vl[*it] - t->nWeight;
            }
            t = t->headLink;
        }
    }

    for (int i = 0; i < keyInfo.size(); i++)
    {
        keyInfo[i].ee = ve[ keyInfo[i].tail ];
    }

    for (int i = (int)keyInfo.size() - 1; i >= 0; i--)
    {
        BaseNode * b = m_Node[keyInfo[i].head].firstIn;
        while (b)
        {
            if (b->headIndex == keyInfo[i].head && b->tailIndex == keyInfo[i].tail)
            {
                keyInfo[i].el = vl[keyInfo[i].head] - b->nWeight;
                break;
            }
            b = b->headLink;
        }
    }

    cout << "关键路径为:" << endl;
    for (int i = 0; i < keyInfo.size(); i++)
    {
        if (keyInfo[i].ee == keyInfo[i].el)
        {
            cout << keyInfo[i].tail << "->" << keyInfo[i].head << "  ";
        }
    }
    cout <<endl<< "over" << endl;
    cout << endl<<endl;

}

int main()
{
    while (true)
    {
        Graph g;
        if (g.Init())
        {
            g.FindKeyPath();
        }
    }
    return 0;
}

这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值