AOE 网络是有向无环加权图,其中顶点表示事件,弧表示活动,权表示活动持续的时间,通常可以用来估算工程完成的时间,即图中从开始点到结束点之间最长的路径对应的时间。请完成一个程序,完成下列任务:
1 、计算 AOE 网络对应的拓扑排序。如果排序结果不唯一,请输出按照从小到大的顺序排列的结果。从小到大的顺序就是输入的节点序列顺序(参见下面关于输入格式的说明)。如图1中满足要求的拓扑排序是: a-b-c-d-e-f-g-h-k ,图2中满足要求的拓扑排序是:v1-v3-v5-v2-v6-v4-v7-v8-v9
2 、计算 AOE 网络的关键路径。注意关键路径可能不唯一,要求输出所有的关键路径。同样,按照是按照从小到大的顺序输出。例,如果得到两条关键路径,分别是0-1-3-6-8-9和0-1-3-4-5-8-9,那么先输出后一条路径,因为两条路径中前三个节点相同,而后一条路径第四个节点的编号小。
测试用例的输入输出格式说明:
输入:
节点的个数,边的条数;
各个节点的名称序列
边: < 起点 , 终点 , 权值 > 。说明起点和终点是在各个点在输入序列中的位置,如图1中边 表示为 <0,1,6> 。
输出:
拓扑排序;
关键路径
测试用例1是与图1相对应的,测试用例2是与图2相对应的。
测试输入 | 期待的输出 | 时间限制 | 内存限制 | 额外进程 | |
---|---|---|---|---|---|
测试用例 1 | 以文本方式显示
|
以文本方式显示
|
1秒 | 64M | 0 |
测试用例 2 | 以文本方式显示
|
以文本方式显示
|
1秒 | 64M | 0 |
测试用例 3 | 以文本方式显示
|
以文本方式显示
|
1秒 | 64M | 0 |
对有向图,每个顶点被指向的箭头个数,就是它的入度,从这个顶点指出去的箭头个数,就是它的出度。一个顶点的入度与出度之和称为该顶点的度。
邻接矩阵:按列遍历矩阵,累计每列1的个数,就是第j个顶点的入度。按层遍历矩阵,累计每行1的个数,就是第i个顶点的出度(i,j均从0开始)【邻接矩阵好做一点,但是用例可能是稀疏矩阵】
邻接表:计算出度时,遍历所求节点后的结点,不为0的时候,count++,然后指针后移,直到尾部(也可通过边算)。计算入度时,外循环遍历每个顶点,内循环检测该节点边是否连有所求节点,若有则sum++。
将入度为0的点弹出,并更新还在其后各点的入度,重复操作。(由于入度为0的点不唯一,拓扑排序结果不唯一,)
本题要求由小到大顺序排列,可将编号存入数组,按照下标读取“大小”。
最长权重的路径就是关键路径,在实际意义上等同于完成一件事的最短必需时间的方案。
顶点表示事件,边表示活动,通过顶点算边。
通过拓扑排序求出事件最早发生时间,反向推导求出事件最晚发生时间,通过事件最早发生时间求出活动最早发生时间,活动最早发生时间等于 from(箭头开始方向的事件最早发生时间),通过活动最早发生时间求出活动最晚发生时间,活动最晚发生时间等于 to - weight(箭头结束方向的事件发生时间 - 权重),通过(活动最晚发生时间-活动最早发生时间)求出关键路径。
(发现了一个算法可以算关键路径还不用建邻接表,嘿嘿,再配合正则表达式来读取,嘶,完美)
出题人NM!为什么不好好的按逻辑出题,我就想用邻接矩阵偷个懒,一开始以为是先对同层级的(入度同时为零)排序一下,结果一看第二个用例v2在v6前面,真ex人啊,不过这也还好,算我自己的问题吧。
但是这乐学编译器怎么还不升级,都不支持regex,服了,给我一直RE,结果一搜是编译器版本的问题,我都忘了乐学只有gcc4.8,服了,输入格式ex人,不想写了,扒代码去了。
贴个源码(我的偷懒版代码,不想改了,就这样吧)
(过不了用例,只能在自己电脑上跑,乐学***,还有就是输出的排序结果顺序和要求不太一样(第二个用例,感觉都不算是宽度优先了))
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
const int M = 5e4 + 5;
struct Edges
{
int in;
int out;
int weight;
} edge[M];
struct Output
{
string s;
} output[M];
int node[M], distant[M], degree_in[M];
int sourcepoint;
vector> graph;
vector ans;
vector in;
void topo_sort(int point_number, int sourcepoint)
{
for (int i = 0; i < point_number; i++)
for (auto j : graph[i])
in[j]++;
queue q;
q.push(sourcepoint);
ans.push_back(sourcepoint);
while (!q.empty())
{
int temp = q.front();
q.pop();
vector pre;
for (auto i : graph[temp]){
in[i]--;
if (in[i] == 0){
q.push(i);
pre.push_back(i);
}
}
sort(pre.begin(), pre.end());
ans.insert(ans.end(), pre.begin(), pre.end());
pre.clear();
}
}
void bellman(int point_number, int edge_number)
{
memset(node, 0, sizeof(node));
memset(distant, 0, sizeof(distant));
for (int k = 1; k < point_number; k++){
int flag = 0;
for (int i = 1; i <= edge_number; i++){
if ((distant[edge[i].in] < distant[edge[i].out] + edge[i].weight) || ((distant[edge[i].in] == distant[edge[i].out] + edge[i].weight) && (edge[i].out < node[edge[i].in]))){
distant[edge[i].in] = distant[edge[i].out] + edge[i].weight;
node[edge[i].in] = edge[i].out;
flag = 1;
}
}
if (flag == 0)
break;
}
while (sourcepoint != 0){
cout<
找代码去咯!(附个链接)
计算工程完成的关键路径(C++语言)-CSDN博客