二维的最短路。
题意:无向图,节点之间除了边外有“快捷方式”,快捷方式可以看作特殊的边,从起点到终点,给定时限,求使用快捷方式的最少次数。
dist[i][j] :到达第i个点,且经过了j个快捷路径的最短时间。
优先队列的最短路优化。
1。如果已经走到终点,还是要继续扩展,因为可能出现使用快捷方式更少的方案。
2。如果已经到终点,可以用当前这个快捷方式数作为限制,继续扩展的节点的使用快捷方式数要小于这个值。
3。如果以前经过这个节点,这次再经过时快捷方式数必须更少,才有必要扩展。
4。如果超过时限的节点不扩展。
#include <cstdio> #include <cstring> #include <vector> #include <algorithm> #include <queue> using namespace std; #define N 102 #define E 10020 #define inf 0x3f3f3f3f struct node { int u, l, s; node (int a=0, int b=0, int c=0): u(a), l(b), s(c) {} bool operator < (const node &a) const { return l > a.l; } }; struct Node { int u, l; Node(int a=0, int b=0): u(a), l(b) {} }; vector<Node> g[N], sg[N]; int n, m, S, in, out, t; bool inq[N][E]; int dist[N][E]; int spfa() { priority_queue<node> Q; int limit = S; node x, y; memset(inq, false, sizeof(inq)); for (int i=1; i<=n; i++) for (int j=0; j<=S; j++) dist[i][j] = inf; Q.push(node(in, 0, 0)); dist[in][0] = 0; while (!Q.empty()) { x = Q.top(); Q.pop(); if (x.u == out && x.s < limit) limit = x.s; if (!inq[x.u][x.s]) { for (size_t i=0; i<g[x.u].size(); i++) { y.u = g[x.u][i].u; y.l = x.l + g[x.u][i].l; y.s = x.s; if (y.l < dist[y.u][y.s] && y.l <= t) { dist[y.u][y.s] = y.l; Q.push(y); } } if (x.s < limit) { for (size_t i=0; i<sg[x.u].size(); i++) { y.u = sg[x.u][i].u; y.l = x.l + sg[x.u][i].l; y.s = x.s + 1; if (y.l < dist[y.u][y.s] && y.l <= t) { dist[y.u][y.s] = y.l; Q.push(y); } } } } inq[x.u][x.s] = true; } for (int i=0; i<=S; i++) if (dist[out][i] <= t) return i; return -1; } int main() { while (scanf("%d%d", &n, &m) == 2) { int u, v, l; for (int i=0; i<=n; i++) { g[i].clear(); sg[i].clear(); } for (int i=0; i<m; i++) { scanf("%d%d%d", &u, &v, &l); g[u].push_back(Node(v, l)); g[v].push_back(Node(u, l)); } scanf("%d", &S); for (int i=0; i<S; i++) { scanf("%d%d%d", &u, &v, &l); sg[u].push_back(Node(v, l)); sg[v].push_back(Node(u, l)); } scanf("%d%d%d", &in, &out, &t); int ans = spfa(); if (ans == -1) printf("Impossible\n"); else printf("%d\n", ans); } return 0; }