POJ3662Telephone Lines
题意:从1到n,使第k+1大的路径尽可能小
思路:二分找第k+1条电话线的长度d,用该长度d跑最短路算法,若最短路上的线路长度>=d的总数大于k+1,则该长度过短,反之过长,若最后无法找到则为-1,长度都可行则为0
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<cstring>
using namespace std;
typedef long long ll;
const ll inf=1e9;
const ll mod=1e9+7;
const int maxn=1e6;
const int N=1e5+5;
int head[maxn],to[maxn],nex[maxn],vis[N],x,y,t,n,m,k,K;
ll dis[N],w[maxn],z,ans,l,r;
struct node{
ll u,num;
bool operator < (const node &x) const{
return u>x.u;
}
};
void add(int a,int b,ll c){
to[++k]=b;
nex[k]=head[a];
head[a]=k;
w[k]=c;
}
bool dij(ll mid){
priority_queue<node>p;
memset(vis,0,sizeof(vis));
for(int i=1;i<=n;i++)
dis[i]=inf;
dis[1]=0;
p.push((node){0,1});
while(!p.empty()){
node tmp=p.top();p.pop();
int now=tmp.num;
if(vis[now])continue;
vis[now]=1;
for(int i=head[now];i;i=nex[i]){
int y=to[i];
int tp=1;
if(w[i]<mid)tp=0;
if(dis[y]>dis[now]+tp){
dis[y]=dis[now]+tp;
p.push((node){dis[y],y});
}
}
}
if(dis[n]>K)return 1;
return 0;
}
int main(){
scanf("%d%d%d",&n,&m,&K);
k=0;l=inf,r=0;
memset(head,0,sizeof(head));
for(int i=1;i<=m;i++){
scanf("%d%d%lld",&x,&y,&z);
add(x,y,z),add(y,x,z);
//l=min(l,z);
//r=max(r,z);
}
l=0,r=1e6+2,ans=0;
while(l<=r){
ll mid=(r+l)/2;
if(dij(mid)){
ans=mid,l=mid+1;
}
else {
r=mid-1;
}
}
if(l>1000000) ans=-1;
cout<<ans<<endl;
}