7-12 How Long Does It Take (25 分) 拓扑排序的变形

Given the relations of all the activities of a project, you are supposed to find the earliest completion time of the project.

Input Specification:
Each input file contains one test case. Each case starts with a line containing two positive integers N (≤100), the number of activity check points (hence it is assumed that the check points are numbered from 0 to N−1), and M, the number of activities. Then M lines follow, each gives the description of an activity. For the i-th activity, three non-negative numbers are given: S[i], E[i], and L[i], where S[i] is the index of the starting check point, E[i] of the ending check point, and L[i] the lasting time of the activity. The numbers in a line are separated by a space.

Output Specification:
For each test case, if the scheduling is possible, print in a line its earliest completion time; or simply output “Impossible”.

Sample Input 1:
9 12
0 1 6
0 2 4
0 3 5
1 4 1
2 4 1
3 5 2
5 4 0
4 6 9
4 7 7
5 7 4
6 8 2
7 8 4
Sample Output 1:
18
Sample Input 2:
4 5
0 1 1
0 2 2
2 1 3
1 3 4
3 2 5
Sample Output 2:
Impossible

这题是拓扑排序的变形,这里面使用的拓扑排序算法是以邻接矩阵为基础的,而不等同于往常的邻接表,因为这里要求最大路径,所有也用了一些最短路径算法的变形。
这里面注意以下几点:
1.初始化数组需要在函数里面,不能形如以下代码:

int dist[MAXV][MAXV]={-1};

2.求最长路径和度为0的值进栈必须在dist>=0的条件下进行,因为只有大于等于0的情况下才有路径,计算才有意义,如果没有在该循环内,有可能因为随意初始的dist和distanc值导致计算结果出错或者导致度为0的点连续进栈出栈!
最终代码如下:

#include<iostream>
#include<algorithm>
using namespace std;
const int MAXV = 102;
int dist[MAXV][MAXV];//因为是找最长路径,所以可以初始化为-1
int indergee[MAXV];//先把所有入度初始化为0
int distanc[MAXV];//这里为什么是 - 1?可以为0吗?
int TopSort(int N)
{
	int ans = 0;
	int St[MAXV], top = -1;//建立存储入度为0的栈
	//求所有点的入度值已经在主函数里面实现了
	//把入度为0的顶点入栈
	for (int i = 0;i < N;i++)
		if (indergee[i] == 0)
		{
			top++;
			St[top] = i;
			distanc[i] = 0;//起始点的距离初始化为0
		}
	int cnt;
	while (top > -1)
	{
		cnt = St[top];
		top--;ans++;
		indergee[cnt]--;//这一步为什么可有可无?因为下面的循环主动避免了这个错误
		for (int i = 0;i < N;i++)
		{
			if (dist[cnt][i] >= 0)
			{
				indergee[i]--;
				//这一步为求最大距离,一定要在dist[cnt][i]>=0的条件下求,因为只有在
				//其大于等于0的条件下才有对应路径,如果不在该条件下求,那么随便定义的distanc值
				//可能会影响最终的最大路径
				if (distanc[cnt] + dist[cnt][i] > distanc[i])
					distanc[i] = distanc[cnt] + dist[cnt][i];
				//这一步如果不在dist[cnt][i]>=0的条件下求,其他dist[cnt][i]=-1的条件下,会有一个
				//点影响结果,即出栈的cnt点indergee[cnt]=0,又会进栈造成错误,如果像现在这样
				//将其放入循环里面,则可以主动避免了这个错误
				if (indergee[i] == 0)
				{
					top++;St[top] = i;
				}
			}
		}
	}
	int Max = 0;
	for (int i = 0;i < N;i++)
	{
		if (distanc[i] > Max)
			Max = distanc[i];
	}
	if (ans == N)
		return Max;
	else
		return 0;
}
int main()
{
	int N, M;
	cin >> N >> M;
	for (int i = 0;i < N;i++)
		for (int j = 0;j < N;j++)
			dist[i][j] = -1;//这个为什么不可以在初始化里面使用?
	for (int i = 0;i < N;i++)
	{
		distanc[i] = -1;indergee[i] = 0;
	}
	int start, over, length;
	for (int i = 0;i < M;i++)
	{
		cin >> start >> over >> length;
		dist[start][over] = length;//把距离赋值,并得到对应的入度
		indergee[over]++;//若有入度,则相应点的入度值加一
		if (length > distanc[over])
			distanc[over] = length;
	}
	int Distanc = TopSort(N);
	if (Distanc)
		cout << Distanc << endl;
	else
		cout << "Impossible" << endl;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值