题目概述:
求有依赖关系的工程的最早完工时间。如果不可能,则输出impossible。
思路:
一开始想的是dijkstra求最长路,但是不对,因为dijkstra是单源点,而此题可以有多个源点和汇点。
判是否可行:若不存在源点或汇点则不可行,即至少要有一个入度为0的点和一个出度为0的点。
求最早完成时间:
拓扑排序+关键路径。
利用队列实现,不断将未标记的入度为0的点入队,并将与其相邻的点的入度减去。
if(--in[i]==0) q[++tt] = i;
若未搜过且存在路径,则可更新。
if(!st[i] && g[t][i] >= 0)
dist[i] = max(dist[i], dist[t]+g[t][i]);
更新路径的同时,判断存最长路,这样就可以不用遍历找最长汇点了。
ans = max(ans, dist[i]);
注意路径初始化为负无穷。
//要有一个入度为0的起始点和出度为0的结束点
#include<iostream>
#include<cstring>
#include<vector>
using namespace std;
const int N = 105;
int g[N][N], in[N], out[N];
int n, m, s, e;
int dist[N], q[N*5];
bool st[N];
int main() {
memset(g, -0x3f, sizeof g);
cin >> n >> m;
while(m--) {
int a, b, c;
cin >> a >> b >> c;
g[a][b] = max(g[a][b], c);
in[b] ++, out[a] ++;
}
s = e = -1;
int hh = 0, tt = -1;
for(int i = 0; i < n; ++ i) {
if(in[i] == 0) {
s = i;
q[++ tt] = i;
dist[i] = 0;
}
if(out[i] == 0) e = i;
}
//cout << s << e << endl;
if(s == -1 || e == -1) {
puts("Impossible");
return 0;
}
int ans = 0;
while(hh <= tt) {
int t = q[hh ++];
st[t] = true;
for(int i = 0; i < n; ++ i) {
if(!st[i] && g[t][i] >= 0) {
dist[i] = max(dist[i], dist[t]+g[t][i]);
//printf("t=%d i=%d dist[i]=%d\n",t,i,dist[i]);
ans = max(ans, dist[i]);
if(--in[i]==0) q[++tt] = i;
}//cout << in[4] << endl;
}
}
cout << ans << endl;
return 0;
}