拓扑排序和关键路径

【问题描述】若在带权的有向图中,以顶点表示事件,以有向边表示活动,边上的权值表示活动的开销(如该活动持续的时间),则此带权的有向图称为AOE网。如果用AOE网来表示一项工程,那么,仅仅考虑各个子工程之间的优先关系还不够,更多的是关心整个工程完成的最短时间是多少;哪些活动的延期将会影响整个工程的进度,而加速这些活动是否会提高整个工程的效率。因此,通常在AOE网中列出完成预定工程计划所需要进行的活动,每个活动计划完成的时间,要发生哪些事件以及这些事件与活动之间的关系,从而可以确定该项工程是否可行,估算工程完成的时间以及确定哪些活动是影响工程进度的关键。
【输入形式】第一行输入两个数字,分别表示顶点数和边数;从第二行开始,输入边的信息,格式为(i,j, weight)
【输出形式】关键路径的总时间(最大路径长度),代表关键活动的边,格式为(顶点1,顶点2),按大小顺序排列
【样例输入】
6 8
0 1 3
0 2 2
1 3 2
1 4 3
2 3 4
2 5 3
3 5 2
4 5 1
【样例输出】

8

0 2

2 3

3 5

#include<iostream>
#include<stack>
#include<vector>
#define maxsize 50
using namespace std;
int n;//顶点个数
int m;//边的条数(活动个数)
int indegree[maxsize];//入度
int ve[maxsize];//事件开始最找时间
int vl[maxsize];//事件开始最晚时间
//int e[maxsize];//活动开始最早时间
//int l[maxsize];//活动开始最晚时间
//int d[maxsize];//活动的松弛时间,为0则为关键活动
int g[maxsize][maxsize];//邻接矩阵
int longestPath;//最长路径的长度
stack<int>s1, s2;//分别用于拓扑序列与逆拓扑序列
vector<int>v;//存储关键路径,便于输出
void initGraph()
{
	for (int i = 0; i < m; i++)
	{
		int v1, v2, weight;
		cin >> v1 >> v2 >> weight;
		g[v1][v2] = weight;
		indegree[v2]++;
	}
}
void topologicalSort()
{
	fill(ve, ve + maxsize, 0);//初始化最早发生时间
	for (int i = 0; i < n; i++)
	{
		if (indegree[i] == 0)
		{
			s1.push(i);
		}
	}
	while (!s1.empty())
	{
		int top = s1.top();
		s2.push(top);//存放逆拓扑序列
		s1.pop();
		for (int i =0; i < n; i++)
		{
			if (g[top][i]!=32767)
			{
				indegree[i]--;
				if (indegree[i] == 0)
				{
					s1.push(i);
				}
				//按拓扑序列计算事件最早发生时间
				if (g[top][i]+ve[top] > ve[i])//注意
				{
					ve[i] = g[top][i]+ve[top];
				}
			}
		}
	}
}
void CriticalPath()//关键路径
{
	//计算vl[i]//时间发生的最晚时间
	for (int i = 0; i < n; i++)
	{
		vl[i] = ve[n - 1];//将各顶点时间最晚发生时间初始化为汇点的最早发生时间
	}
	while (!s2.empty())
	{
		int top = s2.top();
		s2.pop();
		for (int i = 0; i < n; i++)
		{
			if (g[top][i] != 32767)
			{
				if (vl[i]-g[top][i] < vl[top])
				{
					vl[top] = vl[i]-g[top][i];
				}
			}
		}
	}
	//计算e[i],l[i]和关键活动
	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < n; j++)
		{
			if (g[i][j]!= 32767)
			{
				int ei = ve[i];
				int li = vl[j] - g[i][j];
				if (ei == li)
				{
					v.push_back(i);
					v.push_back(j);
				}
			}
		}
	}
}
void printAns()
{
	longestPath = ve[n - 1];
	cout << longestPath << endl;
	for (int i = 0; i < (signed)v.size(); i++)
	{
		cout << v[i] << " ";
		if (i % 2 ==1)
		{
			cout << endl;
		}
	}
}
int main()
{
	cin >> n >> m;
	fill(indegree, indegree + maxsize, 0);
	fill(g[0], g[0] + maxsize * maxsize, 32767);
	initGraph();
	topologicalSort();
	CriticalPath();
	printAns();
	//system("pause");
	return 0;
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值