双调路径node
思路:咱们能够容易想到,经过不一样的边到达某个点的时间和金钱是不同的,这是难点。咱们发现点数n = 100,权值t,c = 100,若是咱们分别维护时间权值为x时,到达该城市的最少金钱是多少,即d[城市][时间] = 金钱,由于 n = 100, t,c = 100,说明咱们须要维护 n*t 个点的值,则边数为 n * t * m = 3e6,咱们能够用spfa解决。ios
#include <iostream> #include <cstdio> #include <algorithm> #include <set> #include <vector> #include <queue> using namespace std; #define ll long long #define pb push_back #define fi first #define se second const int INF = 2e4; struct node { int v, c, t; }; void SPFA(int n, int S, int T, vector<vector<node> >& E) { int _size = n * 100; vector<vector<bool> > vis(n + 1, vector<bool>(_size + 100, 0)); vector<vector<int> > d(n + 1, vector<int>(_size + 100, INF)); queue<pair<int, int> > que; vis[S][0] = true; d[S][0] = 0; que.push(make_pair(S, 0)); while (!que.empty()) { int u = que.front().fi; int w = que.front().se; que.pop(); vis[u][w] = false; for (auto e : E[u]) { if (w + e.t > n * 100) continue; //最多 n * 100 的时间消耗,没有限制,则d[x][∞]会一直更新 if (d[e.v][w + e.t] > d[u][w] + e.c) { d[e.v][w + e.t] = d[u][w] + e.c; if (!vis[e.v][w + e.t]) { vis[e.v][w + e.t] = true; que.push(make_pair(e.v, w + e.t)); } } } } int ans = 0; int Min = INF; for (int i = 0; i <= n * 100; ++i) { if (d[T][i] < Min) { ++ans; Min = d[T][i]; } } printf("%d\n", ans); // cout << "this" << endl; } void solve() { int n, m, S, T; scanf("%d%d%d%d", &n, &m, &S, &T); vector<vector<node> > E(n + 1); int u, v, c, t; for (int i = 0; i < m; ++i) { scanf("%d%d%d%d", &u, &v, &c, &t); E[u].pb({ v, c, t }); E[v].pb({ u, c, t }); } SPFA(n, S, T, E); } int main() { // ios::sync_with_stdio(false); // cin.tie(0); cout.tie(0); // freopen("C:\\Users\\admin\\Desktop\\input.txt", "r", stdin); // freopen("C:\\Users\\admin\\Desktop\\output.txt", "w", stdout); solve(); // cout << "not error" << endl; return 0; }