题意:给出一个有向图,通过每条边花费的时间wi以及每条边的通行时间[bi,ei],问起点到终点路上花费时间(到达时间-出发时间,时间默认最开始是0)最短是多少。
其实就是一个加了限制条件的最短路,SPFA可以做到,其实SPFA是可以加很多扩展内容。
但是注意,由于有通行时间的存在,中途有可能需要等待,而答案要求是到达时间减去出发时间,所以这个等待要尽量放在开始之前,就是尽量晚出发。然而我们并不知道到底是哪个时间出发比较好,所以我们枚举这个出发时间,再用SPFA求最短路。
d[i]表示到i的最短时间(加上出发前的等待时间,就是说d[s] = k,k是所枚举的出发时间,这样d[i]值也就代表着走到i点时的时间),SPFA中需要扩展的内容仅仅是在松弛条件中加上关于通行时间的特判:如果需要等待,那么就要加上等待的时间。再说清楚点,原本是d[v] > d[u]+w的判断变成了d[v] > max(d[u], b) + w && d[u]+w <= e,后一半是要保证在结束通行前可以通过这条边,前一半里的max就是,如果需要等待,那么从u出发时间就是b而不是d[u],到达点v的时间d[v]就变成了从u出发的时间b加上通过这条边本身需要的时间w。
#include <cstdio>
#include <algorithm>
#include <vector>
#include <queue>
#include <cstring>
using namespace std;
int n, m, s, t, ans = 1<<30, d[101], Mn = 1<<30, Mx;
bool inq[101];
vector <int> G[101];
queue <int> q;
struct edge{
int u, v, w, b, e;
}E[1001];
void read(){
scanf("%d %d %d %d", &n, &m, &s, &t);
for(int i = 1; i <= m; i++){
scanf("%d %d %d %d %d", &E[i].u, &E[i].v, &E[i].b, &E[i].e, &E[i].w);
if(E[i].e - E[i].b + 1 < E[i].w) continue;
G[E[i].u].push_back(i);
Mn = min(Mn, E[i].b);
Mx = max(Mx, E[i].e);
}
}
void spfa(int k){
memset(d, 0x7f, sizeof d);
d[s] = k;
q.push(s);
while(!q.empty()){
int u = q.front(); q.pop();
inq[u] = 0;
for(int i = 0; i < G[u].size(); i++){
int t = G[u][i], v = E[t].v, b = E[t].b, e = E[t].e, w = E[t].w;
if(d[v] > max(d[u], b) + w && d[u]+w <= e){
d[v] = d[u] + w;
if(b > d[u]) d[v] += b-d[u];
if(!inq[v]) q.push(v), inq[v] = 1;
}
}
}
}
int main()
{
read();
for(int i = Mn; i <= Mx; i++){
spfa(i);
ans = min(ans, d[t]-i);
}
if(ans <= 1e6) printf("%d", ans);
else printf("Impossible");
}