BZOJ#3245
3245. 最快路线
思路:
最短路,d[i][j],表示在i号点,速度为j的最短距离,记录每次转移的状态即可
代码:
#include <bits/stdc++.h>
#define int long long
int _ = 0, Case = 1;
using namespace std;
#define all(v) begin(v),end(v)
#define nline '\n'
const int N = 550;
struct T {
int ver, v, l;
};
vector<T> h[N];
int vis[N][N];
using PII = pair<int, int>;
PII pre[N][N];
double d[N][N];
struct S {
int ver, v;
double t;
bool operator<(const S &s) const {
return t > s.t;
}
};
void dijkstra(int ed) {
priority_queue<S> q;
q.push({0, 70, 0.0});
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
d[i][j] = 1e18;
}
}
d[0][70] = 0;
while (q.size()) {
auto [ver, v, t] = q.top();
q.pop();
if (vis[ver][v]) continue;
vis[ver][v] = 1;
for (auto [i, cv, cl] : h[ver]) {
if (!cv) cv = v;
double ct = cl * 1.0 / cv * 1.0;
if (d[i][cv] > ct + t ) {
d[i][cv] = ct + t;
pre[i][cv] = {ver, v};
q.push({i, cv, d[i][cv]});
}
}
}
double mmin = 1e18;
int cv = 0;
for (int i = 0; i < N; i++) {
if (d[ed][i] < mmin) {
mmin = d[ed][i];
cv = i;
}
}
vector<int> v;
int x = ed;
for (;;) {
v.push_back(x);
if (x == 0) break;
auto [tx, ty] = pre[x][cv];
x = tx, cv = ty;
}
reverse(all(v));
for (auto i : v) cout << i << ' ';
}
void solve(int Case) {
int n, m, d;
cin >> n >> m >> d;
for (int i = 1; i <= m; i++) {
int a, b, v, l;
cin >> a >> b >> v >> l;
h[a].push_back({b, v, l});
}
dijkstra(d);
}
signed main() {
ios::sync_with_stdio(false); cin.tie(nullptr);
// for (cin >> _, Case = 1; Case <= _; Case++)
solve(Case);
return 0;
}