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 <vector>
# include <queue>
using namespace std;
const int maxn = 100;
typedef struct edge {
int weight;
int start, end;
struct edge* next;
edge(int w, int s, int e):weight(w), start(s), end(e){}
}edge;
struct vertex {
struct edge *start;
vertex():start(nullptr){}
}graph[maxn];
int rudu[maxn],completion[maxn];
int chudu[maxn];
vector<int>v; //用来记录入度为0的顶点,即下一个将被摘去的边的起始节点
vector<int>vv; //用来记录出度为0的顶点,即汇点(题目中可能有多个源点多个汇点)
int main() {
int n, m;
cin >> n >> m;
//建图,n是顶点个数,m是边条数
for (int i = 0; i < m; ++i) {
int start, end, weight;
cin >> start >> end >> weight;
edge *e = new edge(weight, start, end);
e->next = graph[start].start;
graph[start].start = e;
rudu[end]++;
chudu[start]++;
}
for (int i = 0; i < n; ++i)
if (chudu[i] == 0)
vv.push_back(i);
for (int i = 0; i < n; ++i)
//入度为0的结点被加入到vector中
if (rudu[i] == 0)
v.push_back(i);
while (!v.empty()) {
int temp = v.back();
v.pop_back();
edge* e = graph[temp].start;
while (e) {
if (completion[e->end] < completion[e->start] + e->weight)
completion[e->end] = completion[e->start] + e->weight;
rudu[e->end]--;
chudu[e->start]--;
if (!rudu[e->end])
v.push_back(e->end);
graph[temp].start = e->next;
e = e->next;
}
}
//扫描一遍图,如果此时其中还有边,那么就一定是有环,无法拓扑排序
bool res = true;
for (int i = 0; i < n; ++i)
if (graph[i].start != nullptr)
res = false;
priority_queue<int>que;
if (res) {
//拓扑序列存在,那么将输出vv(初始出度为0的顶点集合)中结点的最长完成时间
for (int i = 0; i < vv.size(); ++i)
que.push(completion[vv[i]]);
cout << que.top() << endl;
}
else
cout << "Impossible" << endl;
return 0;
}