计算工程完成的关键路径

选作.计算工程完成的关键路径

说明: 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中边 <a,b> 表示为 <0,1,6> 。

输出:

拓扑排序;

关键路径
在这里插入图片描述
在这里插入图片描述
测试用例0是与图1相对应的,测试用例1是与图2相对应的。
在这里插入图片描述
过程过于繁琐了,比如没必要用顶堆和两次TP,但是写的时候思路不够清晰…
其实大部分思考过程都在书上了,问题在于如何以正确的格式输出,这里借鉴了一下学长的思路,在建立邻接表的时候就先排好序,后来输出的顺序就能保持一致了,因为测试用例比较短,所以冒泡排序就能解决问题~

#include <bits/stdc++.h> 
#pragma warning(disable:4996)
using namespace std;
int indegree[100];
int outdegree[100];
int testindegree[100];
int ve[100];
int vl[100];
int top[100][100];
int topo[55], path[100];
stack <int> T;
priority_queue<int, vector<int>, greater<int> > que[100];//这一步不必要,创建的原因是最初不知道先排序的思路时想到的一种排序方式
typedef struct node
{
	int adjvex;
	int weight;
	struct node* next;
}edgenode;

typedef struct vnode
{
	char vertex[10];
	edgenode* firsteage;
}vertexnode;

typedef struct
{
	vertexnode adjlist[100];
	int n, e;
}linkedgraph;
linkedgraph g;
//上面三项是创建邻接表必不可少的
void creat(linkedgraph* g)//建立邻接表,其中本题需要权值,若不需要权值也可通过此方式建立
{
	int i, j, k, weight;
	int flag1 = 0;
	int flag2 = 0;
	char f;
	char str[10000];
	memset(str, 0, sizeof(str));
	edgenode* s;
	scanf("%d,%d", &g->n, &g->e);
	getchar();
	cin >> str;
	int length = strlen(str);
	for (i = 0; i < length; i++)
	{
		if (str[i] != ',') {
			g->adjlist[flag1].vertex[flag2] = str[i];
			flag2++;
		}
		else {
			g->adjlist[flag1].vertex[flag2] = 0;
			g->adjlist[flag1].firsteage = NULL;
			flag2 = 0;
			flag1++;
		}
		g->adjlist[i].firsteage = NULL;
	}
	g->adjlist[flag1].vertex[flag2] = 0;
	for (k = 0; k < g->e; k++)
	{
		cin >> f >> i >> f >> j >> f >> weight >> f;
	L:	char ah = getchar();

		s = (edgenode*)malloc(sizeof(edgenode));
		s->adjvex = j;
		s->weight = weight;
		s->next = g->adjlist[i].firsteage;
		g->adjlist[i].firsteage = s;
		if (ah == '\n')
			break;
		else if (ah == '<') {
			k++;
			cin >> i >> f >> j >> f >> weight >> f;
			goto L;
		}
	}
	edgenode* m, * n;
	for (k = 0; k < g->n; k++) {//链表冒泡排序,目的是在临接路径中排好顺序,在输出时顺序就
		for (m = g->adjlist[k].firsteage; m != NULL; m = m->next)
			for (n = g->adjlist[k].firsteage; n != NULL; n = n->next)
				if (m->adjvex < n->adjvex) {
					int t1 = m->adjvex; m->adjvex = n->adjvex; n->adjvex = t1;
					int t2 = m->weight; m->weight = n->weight; n->weight = t2;
				}
	}
}
//入度和出度测量~可以认为是度的测量
void inDegree(linkedgraph* g)
{
	edgenode* p;
	int i, outD;
	for (i = 0; i < g->n; i++)
	{
		outD = 0;
		p = g->adjlist[i].firsteage;
		while (NULL != p)
		{
			outD++;
			testindegree[p->adjvex]++;
			indegree[p->adjvex]++;
			p = p->next;
		}
		outdegree[i] = outD;
	}
}
//第一次tp输出拓扑路径~参考《数据结构》
void ToplogicalSort(linkedgraph* g) {
	priority_queue<int, vector<int>, greater<int> > S;
	edgenode* p;
	int i, k;
	int count = 0;
	for (i = 0; i < g->n; i++)
		if (!indegree[i]) S.push(i);
	while (!S.empty()) {
		i = S.top();
		S.pop();
		cout << g->adjlist[i].vertex;
		++count;
		for (p = g->adjlist[i].firsteage; p != NULL; p = p->next) {
			k = p->adjvex;
			indegree[k]--;
			if (!indegree[k]) {
				S.push(k);
			}
		}
		if (S.empty()) {
			cout << endl;
		}
		else
			cout << "-";
	}
}
bool Toplogicalorder(linkedgraph* g) //第二次TP,其实繁琐化了,完全可以并入第一个中
{
	stack <int> S;
	edgenode* p;
	int i, j, k;
	int count = 0;
	memset(ve, 0, sizeof(ve));
	for (i = 0; i < g->n; i++)
		if (!testindegree[i]) S.push(i);
	while (!S.empty()) {
		j = S.top();
		S.pop();
		T.push(j);
		topo[count] = j;
		++count;
		for (p = g->adjlist[j].firsteage; p; p = p->next) {
			k = p->adjvex;
			if (--testindegree[k] == 0) S.push(k);
			if (ve[j] + p->weight > ve[k]) ve[k] = ve[j] + p->weight;
		}
	}
	if (count < g->n) {
		return false;
	}
	else
		return true;
}
void printpath(int top, int end, linkedgraph* g) //递归输出法
{
	int ee, el, k, dut;
	edgenode* p;
	int u = path[top - 1];
	if (u == end) {
		cout << g->adjlist[path[0]].vertex;
		for (int i = 1; i < top; i++)
			printf("-%s", g->adjlist[path[i]].vertex);
		printf("\n");
		return;
	}
	for (p = g->adjlist[u].firsteage; p != NULL; p = p->next) {
		k = p->adjvex;
		dut = p->weight;
		ee = ve[u];
		el = vl[k] - dut;
		if (ee == el) {
			path[top++] = k;
			printpath(top, end, g);
			top--;
		}
	}
}
void CriticalPath(linkedgraph* g)//还是参见《数据结构》
{
	edgenode* p;
	int i, j, k, dut, ee, el;
	char tag;
	for (i = 0; i < g->n; i++)
		vl[i] = ve[g->n - 1];
	while (!T.empty())
		for (j = T.top(), T.pop(), p = g->adjlist[j].firsteage; p != NULL; p = p->next) {
			k = p->adjvex;
			dut = p->weight;
			if (vl[k] - dut < vl[j]) vl[j] = vl[k] - dut;
		}
	path[0] = topo[0];//path其实不必要
	printpath(1, topo[g->n - 1], g);
}
int main() {
	creat(&g);
	inDegree(&g);
	if (Toplogicalorder(&g) == false) {
		cout << "NO TOPOLOGICAL PATH" << endl;
		return 0;
	}
	ToplogicalSort(&g);
	CriticalPath(&g);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值