在郊区有 NN 座通信基站,PP 条 双向 电缆,第 ii 条电缆连接基站 AiAi 和 BiBi。
特别地,11 号基站是通信公司的总站,NN 号基站位于一座农场中。
现在,农场主希望对通信线路进行升级,其中升级第 ii 条电缆需要花费 LiLi。
电话公司正在举行优惠活动。
农产主可以指定一条从 11 号基站到 NN 号基站的路径,并指定路径上不超过 KK 条电缆,由电话公司免费提供升级服务。
农场主只需要支付在该路径上剩余的电缆中,升级价格最贵的那条电缆的花费即可。
求至少用多少钱可以完成升级。
输入格式
第 11 行:三个整数 N,P,KN,P,K。
第 2..P+12..P+1 行:第 i+1i+1 行包含三个整数 Ai,Bi,LiAi,Bi,Li。
输出格式
包含一个整数表示最少花费。
若 11 号基站与 NN 号基站之间不存在路径,则输出 −1−1。
数据范围
0≤K<N≤10000≤K<N≤1000,
1≤P≤100001≤P≤10000,
1≤Li≤1000000
题解:
用二分法找长度,找出最短路中小于这个长度的边为k个的长度
用spfa算法找最短路,如果加入最短路的边小于本次查找的长度就将这个边的权重计为1
#include <cstring>
#include <iostream>
#include <algorithm>
#include<queue>
using namespace std;
const int N = 100010, M = 100010;
int n, m,k;
int dis[N];//当前每个点到1的最短距离
int h[N],w[N],e[N],ne[N],idx;//邻接表储存
bool st[N];
void add(int a,int b,int c)
{
e[idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx++;
}
bool spfa(int v)
{
memset(dis,0x3f,sizeof dis);
dis[1]=0;
queue<int> q;//队列记录被更新过距离的点 只有被更新过的点才会更新其他点的距离
q.push(1);
st[1]=true;
while(q.size())
{
int t=q.front();
q.pop();
st[t]=false;
for(int i=h[t];i!=-1;i=ne[i])//遍历与这个点相连的边
{
int j=e[i];
if(dis[j]>dis[t]+(w[i]>v?1:0))//判断距离是否被更新
{
dis[j]=dis[t]+(w[i]>v?1:0);
if(!st[j])
q.push(j);
{
st[j]=true;//记录这个点是否在队列中 如果已经在队列中则不需要再次加入
}
}
}
}
return dis[n]<=k;
}
int main()
{
scanf("%d%d%d", &n, &m,&k);
memset(h,-1,sizeof h);
for (int i = 0; i < m; i ++ )
{
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
add(a,b,c);
add(b,a,c);
}
int l=0,r=1e6+1;
while(l<r)
{
int mid=r+l>>1;
if(spfa(mid))r=mid;
else l=mid+1;
}
if(r!=1e6+1)cout<<r<<endl;
else cout<<-1<<endl;
return 0;
}