https://vjudge.net/problem/Gym-101490E
给定一个图,问你求他的一条路。
比他的最短路 多du%(这是个阈值,只能少不能多。。酱紫), 然后最大化这条路中 最大的边。
以前是见过这个套路的。忘记在哪了,反正也是没a掉就对了qwq
二分极值。
#include <bits/stdc++.h>
using namespace std;
/* 二分,最短路,
二分的是 松弛操作的界限,没有想到qwq
*/
typedef long long ll;
const int maxn=2e5+5000;
struct Node{
int to,next;
ll dis;
}node[maxn];
int head[maxn];
int len;
ll d[maxn];
bool vis[maxn];
int m,n,du;
ll xz;
void add(int a,int b,ll c){
node[len].to=b;
node[len].dis=c;
node[len].next=head[a];
head[a]=len++;
}
void init(){
len=0;
memset(head,-1,sizeof(head));
}
struct qnode
{ int to;
ll dis;
qnode(int _a,ll _b){to=_a,dis=_b;}
bool operator<(const qnode&r)const{
return dis>r.dis;
}
};
bool dij(ll lim){
priority_queue<qnode>q;
for(int i=0;i<maxn;i++)
d[i]=1e17;
memset(vis,false,sizeof(vis));
q.push(qnode(1,0));
d[1]=0;
vis[1]=true;
while(!q.empty()){
qnode u=q.top();
q.pop();
vis[u.to]=false;
for(int i=head[u.to];i!=-1;i=node[i].next){
int to=node[i].to;
int diss=node[i].dis;
if(diss<=lim&&d[to]>d[u.to]+diss){
d[to]=d[u.to]+diss;
if(!vis[to]){
vis[to]=true;
q.push(qnode(to,d[to]));
}
}
}
}
//cout<<d[m]<<"haha"<<lim<<endl;
if(d[m]<=xz)
return true;
return false;
}
int main()
{ int a,b;ll c;
while(~scanf("%d%d%d",&m,&n,&du)){
init();
ll big=-1;
for(int i=1;i<=n;i++){
scanf("%d%d%lld",&a,&b,&c);
add(a,b,c);
add(b,a,c);
big=max(big,c);
}
ll r=big*2;
ll l=0;
dij(1e7);
xz=((1.0*d[m])/(1.0*100))*(100+du);
//cout<<xz<<"lim"<<endl;
ll ans=big;
//cout<<"jj"<<ans<<endl;
while(l<=r){
ll mid=(l+r)/2;
if(dij(mid)){
ans=mid;
r=mid-1;
}
else
l=mid+1;
}
printf("%lld\n",ans);
}
return 0;
}