这是一道二分搜索题,在判断条件上使用Dijkstra求最少的花费,令mid为所需的答案,那么长度大于mid即为需要免费的电线,这些电线的数量与k比较后确定答案的位置。
#include <cstdio>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
const int inf = 1000 + 10;
const int maxn = 1000 + 10;
const int maxp = 10000 + 10;
const int maxl = 1000000 + 10;
typedef pair<int, int> P;
struct pole {
int b, l;
pole() {}
pole(int b, int l) : b(b), l(l) {}
};
vector<pole> G[maxp];
int d[maxn];
int n, p, k;
//x长度内免费
//返回路线上大于k的边数即所需要免费的数量
int Dijkstra(int s, int x) {
priority_queue<P, vector<P>, greater<P> > que;
fill(d, d + n, inf);
d[s] = 0;
que.push(P(0, s));
while (!que.empty()) {
P p = que.top();
que.pop();
int v = p.second;
if (d[v] < p.first)
continue;
for (int i = 0; i < G[v].size(); i++) {
pole e = G[v][i];
//长度大于x的花费记为1
int nd = d[v] + (e.l > x ? 1 : 0);
if (d[e.b] > nd) {
d[e.b] = nd;
que.push(P(d[e.b], e.b));
}
}
}
return d[n-1];
}
int main(int argc, char const *argv[]) {
scanf("%d%d%d", &n, &p, &k);
for (int i = 0; i < p; i++) {
int a, b, l;
scanf("%d%d%d", &a, &b, &l);
a--, b--;
G[a].push_back(pole(b, l));
G[b].push_back(pole(a, l));
}
//二分搜索
//让长度大于mid的免费
int lb = 0, ub = maxl;
while (ub > lb) {
int mid = (lb + ub) / 2;
if (Dijkstra(0, mid) > k) {
lb = mid + 1;
} else {
ub = mid;
}
}
if (lb == maxl) {
puts("-1");
} else {
printf("%d\n", ub);
}
return 0;
}