- 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);
}