第K大的尽量小,这种表述就容易让人想到二分。
蓝书上的解释:因为支付的钱更多时,合法的升级方案一定有包含子花费更少的升级方案,所以答案具有单调性。
那么我们只要把权值大于mid的路径权值设为1,小于mid的置为0,求1到n的最短路是否不超过n即可。
#include <stdio.h> #include <iostream> #include <cstring> #include <algorithm> #include <cmath> #include <queue> #pragma GCC optimize(2) using namespace std; typedef long long LL; typedef pair<LL, int> PII; const int N = 2e4 + 5, mod = 1e9 + 9, INF = 0x3f3f3f3f; int e[N], h[N], ne[N], w[N], d[N]; int n, p, k, idx, ans; bool vis[N]; priority_queue< PII, vector<PII>, greater<PII> > q; void init() { memset(h, -1, sizeof h); memset(d, 0x3f, sizeof d); memset(vis, false, sizeof vis); } void add(int a, int b, int c) { e[idx] = b; w[idx] = c; ne[idx] = h[a]; h[a] = idx++; return ; } int dij(int mid) { memset(d, 0x3f, sizeof d); memset(vis, false, sizeof vis); d[1] = 0; q.push(make_pair(0, 1)); while (!q.empty()) { int x = q.top().second; q.pop(); if (vis[x]) continue; else vis[x] = 1; for (int i = h[x]; i != -1; i = ne[i]) { int y = e[i], z = w[i]; if (z > mid) z = 1; else z = 0; if (d[x] + z < d[y]) { d[y] = d[x] + z; q.push(make_pair(d[y], y)); } } } return d[n]; } int main() { init(); cin >> n >> p >> k; int ed = -INF; while (p--) { int x, y, z; cin >> x >> y >> z; add(x, y, z); add(y, x, z); ed = max(ed, z); } if(dij(0) == INF) { printf("-1\n"); } else { int ll = 0, rr = ed; int mid; while (ll <= rr) { // cout << rr << endl; int mid = (ll + rr) / 2; if (dij(mid) <= k) { ans = mid; rr = mid - 1; } else { ll = mid + 1; } } cout << ans << endl; } }