08-图9 关键活动

这就是大概思路

思路:所谓关键活动即该结点的最早启动时间与最晚启动时间相等。而最早启动时间与图八的一样,关键是获得结点的最晚启动0时间,与最早启动时间相对应,最早启动时间是获得入度为的点---即出发点,最晚启动时间出度为0,逆序遍历,最晚启动时间是后一个结点减活动所需时间中的最小值,遍历时若结点的出度为0则压入队列内,最后比较最早启动时间和最晚启动时间,两者相等,则该节点参与了关键活动,找到该结点指向的另一个结点。

#include<iostream>
using namespace std;
#include<queue>
#define MaxNum 101
#define INF 9999999
using namespace std;
int Node[MaxNum][MaxNum], N, M, indegree[MaxNum] = { 0 }, outdegree[MaxNum] = { 0 }, earlyTime[MaxNum] = { 0 }, lateTime[MaxNum]= {INF};
int getMaxTime(int earlyTime[]) {//找出所有点的最大时间的最大值
	int MaxTime = 0;
	for (int i = 1; i <=N; i++) {
		if (earlyTime[i] > MaxTime) {
			MaxTime = earlyTime[i];
		}
	}
	return MaxTime;
}
int TopSort() {//得到各个活动的最早启动时间
	int counter = 0, MaxTime = 0;//counter为计数器
	queue<int> q;
	for (int i = 1; i <= N; i++) {//将所有入度为0的点加入队列内,即开始的点
		if (indegree[i] == 0) {
			q.push(i);
		}
	}
	while (!q.empty()) {
		int k = q.front();
		q.pop();
		counter++;//计算所有遍历点的个数
		for (int i = 1; i <= N; i++) {
			if (Node[k][i] != INF) {
				if (earlyTime[k] + Node[k][i] > earlyTime[i]) {//如果对于当前的最大时间可以更新的话,进行更新
					earlyTime[i] = earlyTime[k] + Node[k][i];
				}

				if (--indegree[i] == 0) {//如果更新后删除k到i的这条边,意义上是对i的入度减一
					q.push(i);//如果入度为0,则压入队列
				}
			}
		}
	}
	MaxTime = getMaxTime(earlyTime);
	if (counter != N) {
		return -1;
	}
	else {
		return MaxTime;
	}
}
void getLateTime() {//得到各个活动的最晚启动时间,最晚减去最早就是活动的机动时间,
	queue<int>p;
	for (int i = 1; i <= N; i++) {//从最后一个结点开始往后遍历
		if (outdegree[i] == 0) {
			p.push(i);
		}
	}
	while (!p.empty()) {
		int k = p.front();
		p.pop();
		for (int i = 1; i <= N; i++) {
			if (Node[i][k] != INF) {
				if (lateTime[k] - Node[i][k] < lateTime[i]) {
					lateTime[i] = lateTime[k] - Node[i][k];//最小值即为该结点的最晚启动时间
				}
				if (--outdegree[i] == 0) {//如果结点的出度为0,说明之后已经没有结点,压入队列
					p.push(i);
				}
			}
		}
	}
}
int main()
{
	cin >> N >> M;
	for (int i = 1; i <= N; i++) {//对活动图进行初始化
		lateTime[i] = INF;
		for (int j = 1; j <= N; j++) {
			Node[i][j] = INF;
		}
	}
	for (int k = 0; k < M; k++) {
		int i, j, time;//输入数据
		cin >> i >> j >> time;
		Node[i][j] = time;
		indegree[j]++;
		outdegree[i]++;
	}
  int flag=	TopSort();
  if (flag == -1) {
	  cout << "0";
  }
  else {
	  cout << flag << endl;
	  lateTime[N] = flag;
	  getLateTime();
	  for (int i = 1; i <= N; i++) {
		  if (earlyTime[i] != lateTime[i]) {//遍历结点,若最晚时间等于最早时间说明该结点的获得活动为关键活动
			  continue;
		  }
		  else {
			  for (int j = 1; j <= N; j++) {//寻找与i组成关键活动的下一个结点
				  if (earlyTime[j] == lateTime[j] && Node[i][j] != INF&&earlyTime[j] - Node[i][j] == lateTime[i]) {
					  cout << i << "->" << j << endl;
				  }
			  }
		  }
	  }
  }
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值