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");
}
}
结果如下: