1.题目
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
2.译文
给定一个项目所有活动的关系,你需要找出项目的最早完成时间。
输入说明:
每个输入文件包含一个测试用例。每个测试用例以一行开始,包含两个正整数N(≤100),即活动检查点的数量(因此假设检查点从0到N-1编号),和M,即活动的数量。然后跟随M行,每行描述一个活动。对于第i个活动,给出三个非负数字:S[i],E[i]和L[i],其中S[i]是起始检查点的索引,E[i]是结束检查点的索引,L[i]是活动的持续时间。一行中的数字用空格分隔。
输出说明:
对于每个测试用例,如果调度是可能的,则打印出项目的最早完成时间;否则,简单输出"Impossible"。
3.分析
这道题涉及到AOE网和关键路径(感兴趣的可以了解一下),但考察的点很单一,只需要找到最长的路径(最早完成时间)就可以了,通过深度搜索可以找到最长的路径,但前提是图中不能有环,这就涉及到拓扑排序了,建议先了解什么是拓扑排序。
4.代码
#include<iostream>
#include<vector>
using namespace std;
//结构体邻接表存储图
struct edge {
int from, to, w;
edge(int a, int b, int c) { from = a, to = b, w = c; };
};
vector<edge>e[110];
int N, M, S, E, L, re, uns;
int rd[110], dir[110][110000], vis[110];
bool f = false;
//拓扑排序(命名有点随意)
//开始没用栈,出现段错误还是超时来着
void dfs()
{
int i, j, k, count = 0;
int ma[110], top = -1;
for (int i = 0; i < N; i++){
if (!rd[i]) vis[i] = 1, ma[++top] = i;
}
while (top != -1){
j = ma[top--];
count++;
for (int i = 0; i < N; i++) {
if (!vis[i] && dir[j][i]) {
rd[i]--;
}
}
for (int i = 0; i < N; i++) {
if (!rd[i] && !vis[i]) {
vis[i] = 1, ma[++top] = i;
}
}
}
if (count < N) f = false;
else f = true;
}
//深度搜索早最长时间
void dfs1(int u, int time)
{
if (time > re)
re = time;
for (int i = 0; i < e[u].size(); i++){
int v = e[u][i].to;
time += e[u][i].w;
dfs1(v, time);
time -= e[u][i].w;
}
}
int main()
{
cin >> N >> M;
for (int i = 0; i < M; i++) {
cin >> S >> E >> L;
e[S].push_back(edge(S, E, L));
rd[E]++;
dir[S][E] = 1;
}
for (int i = 0; i < N; i++) {
if (!rd[i]){ //从入度为0的地方开始拓扑排序
dfs();
}
}
if (f) {
for (int i = 0; i < N; i++) {
if (!rd[i]) //入度为0的地方深度搜索
dfs1(i, 0);
}
cout << re << endl;
}
else { cout << "Impossible" << endl; }
return 0;
}