【POJ3662】Telephone Lines
题目链接:https://www.acwing.com/problem/content/description/342/
题目大意:给定一张无向带权图 , 求出 1 到 \(n\) 间的所有路径中第 \(k + 1\) 长的边的最小值
solution
二分最小所用的花费 \(w\) , 对于所有电缆 , 若花费大于 \(w\) , 则长度设为 \(1\) , 否则设为 \(0\) , 跑一遍 \(1\)到
\(n\) 间的最短路 , 显然如果 1 到 \(n\) 的最短距离 如果小于等于 \(k\) , 那么就满足要求 , 否则就不满足
复杂度: \(O(n\log m \log w)\)
code
#include<bits/stdc++.h>
using namespace std;
template <typename T> inline void read(T &FF) {
int RR = 1; FF = 0; char CH = getchar();
for(; !isdigit(CH); CH = getchar()) if(CH == '-') RR = -RR;
for(; isdigit(CH); CH = getchar()) FF = FF * 10 + CH - 48;
FF *= RR;
}
inline void file(string str) {
freopen((str + ".in").c_str(), "r", stdin);
freopen((str + ".out").c_str(), "w", stdout);
}
const int N = 1e5 + 10;
int n, p, k;
int now, fst[N], nxt[N], num[N], wi[N];
void add(int u, int v, int w) {
nxt[++now] = fst[u], fst[u] = now, num[now] = v, wi[now] = w;
nxt[++now] = fst[v], fst[v] = now, num[now] = u, wi[now] = w;
}
int vis[N], st[N];
bool check(int ki) {
memset(vis, 0, sizeof(vis));
memset(st, 0x3f, sizeof(st));
priority_queue<pair<int, int> > qi;
qi.push(make_pair(0, 1)); st[1] = 0;
while(!qi.empty()) {
int pi = qi.top().second; qi.pop();
if(vis[pi]) continue;
vis[pi] = true; if(pi == n) break;
for(int i = fst[pi]; i; i = nxt[i])
if(st[pi] + (wi[i] > ki) < st[num[i]])
st[num[i]] = st[pi] + (wi[i] > ki), qi.push(make_pair(-st[num[i]], num[i]));
}
if(st[n] > k) return false;
return true;
}
int main() {
//file("");
int u, v, w, l = 0, r = 1e6, ans = -1;
read(n), read(p), read(k);
for(int i = 1; i <= p; i++)
read(u), read(v), read(w), add(u, v, w);
while(l <= r) {
int mid = (l + r) >> 1;
if(check(mid)) ans = mid, r = mid - 1;
else l = mid + 1;
}
cout << ans << endl;
return 0;
}