Gym - 101490E-最短路限制&二分&好题-Charles in Charge

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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值