3. 关键路径求解

  1. 3. 关键路径求解

【问题描述】AOE网示意图若在带权的有向图中,以顶点表示事件,以有向边表示活动,边上的权值表示活动的开销(如该活动持续的时间),则此带权的有向图称为AOE网。如果用AOE网来表示一项工程,那么,仅仅考虑各个子工程之间的优先关系还不够,更多的是关心整个工程完成的最短时间是多少;哪些活动的延期将会影响整个工程的进度,而加速这些活动是否会提高整个工程的效率。因此,通常在AOE网中 列出完成预定工程计划所需要进行的活动,每个活动计划完成的时间,要发生哪些事件以及这些事件与某活动之间的关系,从而可以确定该项工程是否可行,来估算工程完成的时间以及确定哪些活动是影响工程进度的关键。

   请参考《耿》教材的算法,编程求解上述问题。构建邻接表的函数,可以直接使用实验题“拓扑排序”中的代码。

【输入形式】第一行输入两个数字,依次是顶点数和边数;从第二行开始,输入边的信息,格式为(i  j  weight),i为弧尾顶点编号,j为弧头顶点编号,两个数据间用空格分隔;规定顶点编号从0开始。

【输出形式】关键活动的情况,格式为(顶点1  顶点2),两者间用1个空格分隔。要求:输出表示关键活动的各条弧时,按照弧尾顶点编号从小到大的顺序依次输出各条弧。
【样例输入】

6 8

0 2 2

0 1 3

1 4 3

1 3 2

2 5 3

2 3 4

3 5 2

4 5 1
【样例输出】

0 2

2 3

3 5

【样例说明】输入的(i  j  weight)时,不用输入括号。输出(顶点1  顶点2)时,不用输出括号。

#include <bits/stdc++.h>
using namespace std;
struct edgenode
{
    int adj;
    int weight;
    edgenode *next;
};
typedef struct vnode
{
    int data;
    edgenode *first;
} adjlist[100];
struct graph
{
    adjlist vertices;
    int vexnum, arcnum;
};
int innode[500];      //统计各顶点的入度
int store[500];       //储存拓扑排序后序列
int vl[500], ve[500]; //不用解释了,学了的都懂我这个什么意思
void create(graph **g)
{
    *g = new graph;
    cin >> (*g)->vexnum >> (*g)->arcnum;
    for (int i = 0; i < (*g)->vexnum; i++)
        (*g)->vertices[i].first = NULL;
    for (int q = 0; q < (*g)->arcnum; q++)
    {
        int i, j, weight;
        cin >> i >> j >> weight;
        edgenode *p = new edgenode;
        p->adj = j;
        p->weight = weight;
        p->next = (*g)->vertices[i].first;
        (*g)->vertices[i].first = p;
    }
}
void get_innode(graph *g) //获取入度序列
{
    fill(innode, innode + g->vexnum, 0);
    for (int i = 0; i < g->vexnum; i++)
    {
        edgenode *p = g->vertices[i].first;
        while (p)
        {
            innode[p->adj]++;
            p = p->next;
        }
    }
}
int counts;
void topologicasort(graph *g)
{
    counts = 0;
    fill(ve, ve + g->vexnum, 0);
    get_innode(g);
    stack<int> s;
    for (int i = 0; i < g->vexnum; i++)
        if (!innode[i])
            s.push(i);
    while (!s.empty())
    {
        int invex = s.top();
        store[counts++] = s.top();
        s.pop();
        for (edgenode *p = g->vertices[invex].first; p; p = p->next)
        {
            int outvex = p->adj;
            if (!(--innode[outvex]))
                s.push(outvex);
            if (ve[invex] + p->weight > ve[outvex])
                ve[outvex] = ve[invex] + p->weight;
        }
    }
}
void get_path(graph *g)
{
    int top = counts - 1;
    int invex, outvex;
    invex = store[top--];
    for (int i = 0; i < g->vexnum; i++)
        vl[i] = ve[invex];

    while (top != -1)
    {
        invex = store[top--];
        edgenode *p = g->vertices[invex].first;
        while (p)
        {
            outvex = p->adj;
            if (vl[invex] > vl[outvex] - p->weight)
                vl[invex] = vl[outvex] - p->weight;
            p = p->next;
        }
    }
    for (invex = 0; invex < g->vexnum; invex++)
    {
        edgenode *p = g->vertices[invex].first;
        while (p)
        {
            outvex = p->adj;
            int ee = ve[invex];
            int el = vl[outvex] - p->weight;
            if (ee == el)
                cout << invex << " " << outvex << endl;
            p = p->next;
        }
    }
}
int main()
{
    graph *g;
    create(&g);
    topologicasort(g);
    get_path(g);
}

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Wrong Ansewer

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

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

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

打赏作者

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

抵扣说明:

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

余额充值