题意
传送门 POJ 3662
题意为线缆公司免费提供 条边,问题转化为最小化路径上第 长的边权值。二分答案,将图中权值大于当前二分值的边的权值赋为 1,反之为 0;dijkstra 求最短路,此时的最短路代表从顶点 1 到顶点 N 大于二分值的边的最少使用数,满足使用数小于等于 的最短边权值即答案。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue>
#include <vector>
#define min(a,b) (((a) < (b)) ? (a) : (b))
#define max(a,b) (((a) > (b)) ? (a) : (b))
#define abs(x) ((x) < 0 ? -(x) : (x))
#define INF 0x3f3f3f3f
#define delta 0.85
#define eps 1e-5
#define PI 3.14159265358979323846
#define MAX_V 1005
#define MAX_E 10005
using namespace std;
typedef pair<int, int> P;
struct edge{
int to, cost;
edge(int to, int cost):to(to), cost(cost){}
};
int V, E, K;
vector<edge> G[MAX_V];
int d[MAX_V];
int dijktra(int s, int k){
priority_queue<P, vector<P>, greater<P> > que;
memset(d, 0x3f, sizeof(d));
d[s] = 0;
que.push(P(0, s));
while(!que.empty()){
P p = que.top(); que.pop();
int v = p.second;
if(p.first > d[v]) continue;
for(int i = 0; i < G[v].size(); i++){
edge &e = G[v][i];
// 权值大于需付费用的边权值设为 1, 反之为 0
int d2 = d[v] + (e.cost > k ? 1 : 0);
if(d2 < d[e.to]){
d[e.to] = d2;
que.push(P(d[e.to], e.to));
}
}
}
return d[V - 1];
}
int main(){
while(~scanf("%d%d%d", &V, &E, &K)){
for(int i = 0; i < E; i++){
int a, b, l;
scanf("%d%d%d", &a, &b, &l);
--a, --b;
G[a].push_back(edge(b, l));
G[b].push_back(edge(a, l));
}
bool flag = 1;
int lb = -1, ub = INF;
while(ub - lb > 1){
int mid = (lb + ub) >> 1, cost = dijktra(0, mid);
if(cost <= K) ub = mid;
else{
if(cost == INF){
printf("-1\n");
flag = 0;
break;
}
lb = mid;
}
}
if(flag) printf("%d\n", ub);
}
return 0;
}