【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;
}
posted @ 2020-01-29 12:57  MagicDuck  阅读(238)  评论(0编辑  收藏  举报