Data Structures and Algorithms (English)

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

思路:
这个题目怎么说呢,就是拓扑排序稍微加点东西。什么东西呢,设邻接矩阵为G(代码里面是邻接表,这里为了表述简单)earliest[i]为i结点之间的activity最早完成的时间。从队列弹出结点v,观察其邻接点i,如果,earliest[v]+G[v][i]>earliest[i],就将earliest[i]更新为earliest[v]+G[v][i]>earliest[i]即可。所以代码就是在原来的拓扑排序基础上加上上面的就好了。 需要注意的是我们需要考虑多个终点的情况,我第一次做的时候就没考虑,以为就一个终点,直接输出了earliest[N-1]。现在想想好chun,终点也可能不在最后一个结点啊…所以我怎么干的呢,我就直接输出了earliest数组的最大值。
简单粗暴的代码如下:

#include<stdio.h>
#include<stdlib.h>
#define MaxSize 200
typedef struct  node{
	int index;
	int weight;
	struct node* next;
} G,*LGraph;

typedef struct {
	int left;
	int right;
	int weight;
}edge;

G p[MaxSize];
 
int N, M;
int earliest[MaxSize] = { 0 };
int indegree[MaxSize] = { 0 };

void insert(edge x) {
	LGraph tmp;
	tmp = (LGraph)malloc(sizeof(G));
	tmp->index = x.right;
	tmp->weight = x.weight;
	tmp->next = p[x.left].next;
	p[x.left].next = tmp;
}

/*void print(int left) {
	LGraph tmp = p[left].next;
	while (tmp) {
		printf("%d,%d,%d\n", left, tmp->index, tmp->weight);
		tmp = tmp->next;
	}
}*/
int topsort() {
	/* 首先找出所有入度为0的点进行入队*/
	int cnt = 0;
	int queue[MaxSize], front = 0, rear = 0;
	for (int i = 0;i < N; i++) {
		if (indegree[i] == 0) {
			queue[rear] = i;
			rear = (rear + 1) % MaxSize;
		}
	}
	while (rear != front) {
		int v = queue[front];
		cnt++;
		front = (front + 1) % MaxSize;
		for (LGraph tmp = p[v].next;tmp;tmp = tmp->next) {
			if (--indegree[tmp->index] == 0) {
				queue[rear] = tmp->index;
				rear = (rear + 1) % MaxSize;
			}
			if (earliest[v] + tmp->weight > earliest[tmp->index]) {
				earliest[tmp->index] = earliest[v] + tmp->weight;
			}
		}
	}
	if (cnt < N) {
		return 0;
	}
	else {
		return 1;
	}
}
int max() {
	int ans = earliest[0];
	for (int i = 0;i < N;i++) {
		if (ans < earliest[i]) {
			ans = earliest[i];
		}
	}
	return ans;
}
int main() {
	edge x;
	scanf("%d%d", &N, &M);
	for (int i = 0;i < M;i++) {
		scanf("%d%d%d", &x.left, &x.right, &x.weight);
		indegree[x.right]++; // 累计入度
		insert(x);
	}
	int flag = topsort();
	if (flag) {
		printf("%d", max());
	}
	else {
		printf("Impossible");
	}
}

结果如下:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值