题目
多年以后,笨笨长大了,成为了电话线布置师。由于地震使得某市的电话线全部损坏,笨笨是负责接到震中市的负责人。该市周围分布着
N(1<=N<=1000)
N
(
1
<=
N
<=
1000
)
根据1……n顺序编号的废弃的电话线杆,任意两根线杆之间没有电话线连接,一共有
p(1<=p<=10000)
p
(
1
<=
p
<=
10000
)
对电话杆可以拉电话线。其他的由于地震使得无法连接。第i对电线杆的两个端点分别是ai,bi,它们的距离为
li(1<=li<=1000000)
l
i
(
1
<=
l
i
<=
1000000
)
。数据中每对
(ai,bi)
(
a
i
,
b
i
)
只出现一次。编号为1的电话杆已经接入了全国的电话网络,整个市的电话线全都连到了编号
N
N
的电话线杆上。也就是说,笨笨的任务仅仅是找一条将号和
N
N
号电线杆连起来的路径,其余的电话杆并不一定要连入电话网络。电信公司决定支援灾区免费为此市连接k对由笨笨指定的电话线杆,对于此外的那些电话线,需要为它们付费,总费用决定于其中最长的电话线的长度(每根电话线仅连接一对电话线杆)。如果需要连接的电话线杆不超过k对,那么支出为0.请你计算一下,将电话线引导震中市最少需要在电话线上花多少钱?
输入输出格式
输入格式:
输入文件的第一行包含三个数字n,p,k;
第二行到第p+1行,每行分别都为三个整数ai,bi,li。
输出格式:
一个整数,表示该项工程的最小支出,如果不可能完成则输出-1.
输入输出样例
输入样例#1:
5 7 1
1 2 5
3 1 4
2 4 8
3 2 3
5 2 9
3 4 7
4 5 6
输出样例#1:
4
分析
我们正着想不好想,所以我们可以二分再进行判断,我们二分最大费用,将大于的赋1,否则赋0,走1到n的最短路,若大于k,则表示费用小,使,否则
r=mid−1
r
=
m
i
d
−
1
,这样二分出答案就行了,注意输出-1
上代码
#include<bits/stdc++.h>
using namespace std;
int tot=0,n,p,k,hed[1010],ver[200010],nxt[200010],we[200010],we2[200010],ans,dis[1010];
bool vis[1010];
void add(int x,int y,int z){
ver[++tot]=y,nxt[tot]=hed[x],hed[x]=tot,we[tot]=z;
}
bool check(int x){
memset(we2,0,sizeof(we2));
for(int i=1;i<=tot;i++)
if(we[i]>x)
we2[i]=1;
memset(vis,0,sizeof(vis));
memset(dis,0x3f,sizeof(dis));
queue<int> q;
q.push(1);
vis[1]=1,dis[1]=0;
while(q.size()){
int y=q.front();
q.pop();
vis[y]=0;
for(int i=hed[y];i;i=nxt[i]){
int p=ver[i];
if(dis[p]>dis[y]+we2[i]){
dis[p]=dis[y]+we2[i];
if(!vis[p])
vis[p]=1,q.push(p);
}
}
}
if(dis[n]<=k)
return 1;
return 0;
}
int main(){
scanf("%d%d%d",&n,&p,&k);
for(int i=1,x,y,z;i<=p;i++){
scanf("%d%d%d",&x,&y,&z);
add(x,y,z),add(y,x,z);
}
int l=0,r=2000000;
while(l<=r){
int mid=(l+r)/2;
if(check(mid))
ans=mid,r=mid-1;
else
l=mid+1;
}
if((ans==0)&&(r==2000000))
ans=-1;
printf("%d\n",ans);
return 0;
}