↵
解题思路
可以免费k条路,然后只需要支付权值最大的一条路。二分。对答案进行二分,小于等于mid的时,将路的权值标为0,大于mid时,将路的权值标为1。(mid是需要支付的,免费k条是大于mid的。因为二分枚举的mid就是答案, 然后如果等于mid的话 mid是答案 也成立)然后求最短路。二分的条件是dis[n]小于等于mid,r=mid;dis[n]大于mid,l=mid+1;
#include<stdio.h>
#include<queue>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=1e5+177;
const int inf=0x3f3f3f3;
struct Node{
int next;
int to;
int vul;
}edge[maxn];
int vul[maxn];
struct node{
int x;int y;
};
int head[maxn];
int num_edge=0;
int n,p,k;
int dis[maxn];
bool vis[maxn];
typedef pair<int,int >pa;
void add_edge(int from,int to,int vul){
edge[++num_edge].next=head[from];
edge[num_edge].to=to;
edge[num_edge].vul=vul;
head[from]=num_edge;
}
void init(){
for(int i=0;i<=n+177;i++){
dis[i]=inf;
vis[i]=false;
}
}
void dijkstra(int sta){
init();
dis[1]=0;
priority_queue<pa> pq;
pa now,tmp;
now.first=0;
now.second=sta;
pq.push(now);
while(!pq.empty()){
now=pq.top();
pq.pop();
if(dis[now.second]<now.first){
continue;
}
for(int i=head[now.second];i!=0;i=edge[i].next){
int y=edge[i].to;
int z=vul[i];
if(dis[y]>dis[now.second]+z){
dis[y]=dis[now.second]+z;
tmp.first=-dis[y];
tmp.second=y;
pq.push(tmp);
}
}
}
}
bool jug(int now){
if(now>k){
return true;
}
return false;
}
void change(int now){
for(int i=0;i<=num_edge;i++){
if(edge[i].vul<=now){
vul[i]=0;
}else{
vul[i]=1;
}
}
dijkstra(1);
}
int main(){
cin>>n>>p>>k;
int x,y,z;
for(int i=0;i<p;i++){
cin>>x>>y>>z;
add_edge(x,y,z);
add_edge(y,x,z);
}
int l=0,r=inf;
while(l<r){
int mid=(l+r)/2;
change(mid);
if(jug(dis[n])){
l=mid+1;
}else{
r=mid;
}
}
if(l>=inf){
printf("-1\n");
}else{
printf("%d\n",l);
}
return 0;
}