鄙人不才,此中鄙陋甚多,望海涵!!!
题目描述
在郊区有 N 座通信基站,P 条 双向 电缆,第 i 条电缆连接基站Ai和Bi。
特别地,1 号基站是通信公司的总站,N 号基站位于一座农场中。
现在,农场主希望对通信线路进行升级,其中升级第 i 条电缆需要花费Li。
电话公司正在举行优惠活动。
农产主可以指定一条从 1 号基站到 N 号基站的路径,并指定路径上不超过 K 条电缆,由电话公司免费提供升级服务。
农场主只需要支付在该路径上剩余的电缆中,升级价格最贵的那条电缆的花费即可。
求至少用多少钱可以完成升级。
输入格式
第1行:三个整数N,P,K。
第2..P+1行:第 i+1 行包含三个整数Ai,Bi,Li。
输出格式
包含一个整数表示最少花费。
若1号基站与N号基站之间不存在路径,则输出”-1”。
数据范围
0≤K<N≤1000,
1≤P≤10000,
1≤Li≤1000000
输入样例
5 7 1
1 2 5
3 1 4
2 4 8
3 2 3
5 2 9
3 4 7
4 5 6
输出样例
4
算法:二分加双端队列
C++ 代码
//据题意分析是要寻找从1到n的路径中最小的一条第k+1大的路径,一般像这种要求最大值最小或最小值最大的问题
//都可以用二分来做,但需要找到某种性质,保证答案只在一边,这里我们找到的性质就是二分x(x在答案所在的区间)
//在从1到n的路径中寻找大于x的的边的数量,如果它小于等于k,说明答案在左边,否则在右边,最终一定会找到刚刚
//好大于x的边的数量为k条,继续二分到比x大的边有k+1条时,二分结束,那这样x就刚好为第k+1大的边了!
#include<iostream>
#include<cstring>
#include<deque>
using namespace std;
const int N=1010,M=20010;
int h[N],e[M],ne[M],w[M],idx;
int dist[N];
bool st[N];
int n,p,k;
void add(int a,int b,int c)
{
e[idx]=b,ne[idx]=h[a],w[idx]=c,h[a]=idx++;
}
bool check(int x)
{
memset(dist,0x3f,sizeof dist);
memset(st,0,sizeof st);
dist[1]=0;
deque<int> q;
q.push_back(1);
while(q.size())
{
int t=q.front();
q.pop_front();
if(st[t]) continue;
st[t]=true;
for(int i=h[t];~i;i=ne[i])
{
int j=e[i];
int c=w[i]>x;
if(dist[j]>dist[t]+c)
{
dist[j]=dist[t]+c;
if(c) q.push_back(j);
else q.push_front(j);
}
}
}
return dist[n]<=k;
}
int main()
{
cin>>n>>p>>k;
memset(h,-1,sizeof h);
for(int i=0;i<p;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=l+r>>1;
if(check(mid)) r=mid;
else l=mid+1;
}
if(r==1e6+1) puts("-1");
else cout<< r <<endl;
return 0;
}
今天学到这里,对最短路跑二分不太熟悉。。请问 int c=w[i]>x; 这一句,把小于号改成小于等于,样例出来一个5,我觉得无法理解,请问改为小于等于的时候他代表什么意思呢
大佬您的第一句话貌似可以去掉
您怎么可能是鄙人呢?
大神还差不多......
没有没有,学得越多感觉越菜,因为你以为自己学得多就能做出那些题了,结果还是和原来一样,然后我就感觉一直好菜!
awa