说在前面
并没有什么想说的,但是要保持格式=w=
题目
题目大意
给出一个
个点
条边的无向图,再给出一个常数
定义一条路径的花费为:组成这条路径的边权的最大值
现在需要选择一条从
到
的路径,可以使路径上任意
条边边权变成
,问最小花费
范围:
,
,边权
输入输出格式
输入格式:
第一行三个数字
,含义如题
接下来
行,每行三个整数
描述一条边
输出格式:
输出一个整数表示答案
若无法连通,输出-1
解法
显然的二分答案
先建个图,把所有边的长度设1,跑一遍最短路,确认无解或者答案为0的情况
二分答案的时候,把边权大于当前二分值的,在图中的长度设为1,否则0,然后check最短路是否不超过K即可
下面是代码
#include <queue>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std ;
int N , P , K , head[1005] , tp ;
int len[20005] ;
struct Path{
int pre , to , len ;
} p[20005] ;
template < typename T > void smin( T &x , T y ){ if( x > y ) x = y ; }
template < typename T > void smax( T &x , T y ){ if( x < y ) x = y ; }
void In( int t1 , int t2 ){
p[++tp] = ( Path ){ head[t1] , t2 , 1 } ; head[t1] = tp ;
p[++tp] = ( Path ){ head[t2] , t1 , 1 } ; head[t2] = tp ;
}
int dis[1005] ;
bool inq[1005] ; queue<int> que ;
int Spfa(){
memset( dis , 0x3f , sizeof( dis ) ) ;
dis[1] = 0 ; que.push( 1 ) , inq[1] = true ;
while( !que.empty() ){
int u = que.front() ;
que.pop() , inq[u] = false ;
for( int i = head[u] ; i ; i = p[i].pre ){
int v = p[i].to ;
if( dis[v] > dis[u] + p[i].len ){
dis[v] = dis[u] + p[i].len ;
if( !inq[v] ) que.push( v ) , inq[v] = true ;
}
}
} return dis[N] ;
}
void solve(){
int dist = Spfa() , lf = 0x3f3f3f3f , rg = 0 , ans ;
if( dist == 0x3f3f3f3f ) puts( "-1" ) , exit( 0 ) ;
if( dist <= K ) puts( "0" ) , exit( 0 ) ;
for( int i = 1 ; i <= tp ; i ++ )
smin( lf , len[i] ) , smax( rg , len[i] ) ;
while( lf <= rg ){
int mid = ( lf + rg ) >> 1 ;
for( int i = 1 ; i <= tp ; i ++ )
p[i].len = ( len[i] > mid ) ;
if( ( dist = Spfa() ) <= K )
ans = mid , rg = mid - 1 ;
else lf = mid + 1 ;
} printf( "%d" , ans ) ;
}
int main(){
scanf( "%d%d%d" , &N , &P , &K ) ;
for( int i = 1 , u , v , w ; i <= P ; i ++ ){
scanf( "%d%d%d" , &u , &v , &w ) ;
In( u , v ) ; len[tp] = len[tp-1] = w ;
} solve() ;
}