You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

74 lines
2.5 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> PII;
const int INF = 0x3f3f3f3f;
const int N = 1010; // 1000个点
const int M = 20010; // 10000条记录无向边需要两倍空间
int idx, h[N], e[M], w[M], ne[M];
void add(int a, int b, int c) {
e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx++;
}
int n; // 点数
int m; // 边数
int k; // 不超过K条电缆由电话公司免费提供升级服务
bool st[N]; // 记录是不是在队列中
int dis[N]; // 记录最短距离
// mid指的是我们现在选最小花费
bool check(int mid) {
// 需要跑多次dijkstra所以需要清空状态数组
memset(st, false, sizeof st);
memset(dis, 0x3f, sizeof dis);
priority_queue<PII, vector<PII>, greater<PII>> q;
dis[1] = 0;
q.push({0, 1});
while (q.size()) {
PII t = q.top();
q.pop();
int u = t.second;
if (st[u]) continue;
st[u] = true;
for (int i = h[u]; ~i; i = ne[i]) {
int j = e[i];
int v = w[i] > mid; // 如果有边比我们现在选的这条边大那么这条边对方案的贡献为1反之为0
if (dis[j] > dis[u] + v) {
dis[j] = dis[u] + v;
q.push({dis[j], j});
}
}
}
// 如果按上面的方法计算后n结点没有被松弛操作修改距离则表示n不可达
if (dis[n] == INF) {
puts("-1"); // 不可达,直接输出-1
exit(0);
}
return dis[n] <= k; // 如果有k+1条边比我们现在这条边大那么这个升级方案就是不合法的反之就合法
}
int main() {
memset(h, -1, sizeof h);
cin >> n >> m >> k;
int a, b, c;
for (int i = 0; i < m; i++) {
cin >> a >> b >> c;
add(a, b, c), add(b, a, c);
}
/*
这里二分的是直接面对答案设问: 至少用多少钱 可以完成升级
依题意最少花费其实是所有可能的路径中第k+1条边的花费
如果某条路径不存在k+1条边(边数小于k+1),此时花费为0
同时任意一条边的花费不会大于1e6,所以,这里二分枚举范围:0 ~ 1e6
*/
int l = 0, r = 1e6;
while (l < r) {
int mid = (l + r) >> 1;
if (check(mid)) // check函数的意义如果当前花费可以满足要求那么尝试更小的花费
r = mid;
else
l = mid + 1;
}
printf("%d\n", l);
return 0;
}