浙大数据结构:08-图8 How Long Does It Take (25 分)

08-图8 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

代码

整个问题属于关键路径问题,比较简单,这个代码里面值得参考的大概只有统计邻接表入度的那一部分,写得还算比较简洁。图是用邻接表建图,是一个有向图。

#include<iostream>
#include<queue>
using namespace std;
#define Maxsize 100
/*拓扑排序,考虑使用邻接表建图*/
typedef struct GraphNode* Graph;
typedef int Vertex;
typedef int Weight;
typedef struct LNode* PtrToLNode;
struct LNode {
	Vertex V;
	Weight weight;
	PtrToLNode Next;
	LNode(){}
	LNode(int V2,int w):V(V2),weight(w),Next(NULL){}
};
typedef struct VNode {
	PtrToLNode FirstEdge;
	VNode():FirstEdge(NULL){}
}PtrToLNodeArr[Maxsize];
struct GraphNode {
	int Nv;
	int Ne;
	PtrToLNodeArr Points;
};
Graph BuildGraph(int N, int M) {
	/*建立一个有N个顶点,M条边的有向图*/
	Graph G = new GraphNode;
	G->Nv = N;
	G->Ne = M;
	Vertex v1, v2;
	Weight w;
	PtrToLNode L;
	for(int i=0;i<M;i++){
		cin >> v1 >> v2 >> w;
		L = new LNode(v2,w);
		L->Next = G->Points[v1].FirstEdge;
		G->Points[v1].FirstEdge = L;//有向图只记录v1->v2的
	}
	return G;
}

/*拓扑排序关键路径问题*/
void IndegreeCount(Graph G, int InDegree[]) {
	/*统计G图中的入度,结果写在InDegree[]中*/
	int i, Index;
	PtrToLNode tmp;
	for (int i = 0; i < G->Nv; i++) {//对Nv个点统计入度
		tmp = G->Points[i].FirstEdge;
		while (tmp != NULL) {
			InDegree[tmp->V]++;//第i个点的所有邻接节点V的入度+1
			tmp = tmp->Next;
		}
	}
}
/*
template<class T>
int GetArrSize(const T& Obj) {
	return sizeof(Obj) / sizeof(Obj[0]);
}

void FindInDegIsZero(int InDegree[], queue<Vertex>& q) {
	/*查找InDegree中入度为0的点,并加入队列
	int ArrSize=GetArrSize(InDegree);
	for (int i = 0; i < ArrSize; i++) {
		if (InDegree[i] == 0) {
			q.push(i);
		}
	}
}
*/
/*拓扑排序主函数*/
int TopSorting(Graph G) {
	int InDegree[Maxsize];//统计入度
	int Time[Maxsize];//统计到每个节点最早什么时候完成
	queue<Vertex> q;
	Vertex V;
	for (int i = 0; i < G->Nv; i++) {
		Time[i] = 0;//初始化Time和InDegree的每个节点
		InDegree[i] = 0;
	}
	IndegreeCount(G, InDegree);//统计入度
	
	for (int i = 0; i < G->Nv; i++) {//查找InDegree中入度为0的点,并加入队列
		if (InDegree[i] == 0) {
			q.push(i);
		}
	}

	PtrToLNode tmp;
	Vertex W;
	int Vcout = 0;//统计弹出了多少个节点,判断拓扑排序是否失效,正常应该为G->Nv个点
	while (q.empty() != 1) {
		V = q.front();
		q.pop();//弹出当前节点V
		Vcout++;
		for (tmp = G->Points[V].FirstEdge; tmp != NULL; tmp = tmp->Next) {
			/*对V的下节点W点进行更新*/
			W = tmp->V;
			InDegree[W]--;
			if (InDegree[W] == 0) {
				q.push(W);
			}
			if (Time[V] + tmp->weight > Time[W]) {//如果节点W的时间比V+<v,w>更小,那么选取更大的那个
				Time[W] = Time[V] + tmp->weight;
			}
		}
	}

	int MaxTime = 0;
	for (int i = 0; i < G->Nv; i++) {
		MaxTime = Time[i] > MaxTime ? Time[i] : MaxTime;//选出Time[i]中最大的值
	}

	if (Vcout == G->Nv)return MaxTime;
	else return -1;
}


int main() {
	int N, M;
	cin >> N >> M;
	Graph G;
	G = BuildGraph(N, M);
	int res = TopSorting(G);
	if (res == -1)cout << "Impossible";
	else cout << res;
	return 0;
}

测试结果

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值