POJ 3594 带限制的最短路 枚举+SPFA

来源:互联网 发布:淘宝店铺转让风险 编辑:程序博客网 时间:2024/05/18 00:35
题意:给出一个有向图,通过每条边花费的时间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");}


0 0