(赛后补题)E - Charles in Charge(dij+二分)

原题引入:Every day, Charles drives from his home to work and back. He uses the highways of the country that run from one city to another. Charles has decided that he wants to help the environment by buying an electrical car. Electrical cars, however, are not very common in his country yet. They can only be charged inside a city; there are no charging stations along the highways in between the cities. Moreover, all electrical cars are identical except for one thing: the size of the battery. As batteries are very expensive, Charles would like to buy a car with battery that is as small as possible.

However, this greatly increases the time it takes for him to get home, much to the distaste of his wife, Charlotte. This has spawned an argument, and after much discussion they have decided to compromise: Charlotte is fine with Charles taking a longer route, as long as it its length is at most X \%X% longer than the length of shortest route that Charles could have taken to get home from work by using a regular car. Charles has agreed with this, and he now wants to find a route that minimizes the size of the car battery that he needs, i.e. the route that minimizes the maximum distance that Charles has to drive on a highway without passing through a city.

The amount of time Charles spends to charge his car can be neglected.

题意:n个点,m条路,每条路连接两个城市,给你一个x,让你找一条总长度不超过(1+x)%最短的那条路,然后让这条路上两个城市之间最大长度最小。

思路:首先跑一边dij,求最短路,然后再每次二分一个限度,dij的时候加上判断,如果大于这个限度就不松弛它,最后我们就会发现,二分到最后的答案就是输出答案。

注意,二分的时候需要把左右边界弄得大一点,不然会wa,然后N也要设置的大一点。

#include <bits/stdc++.h>

using namespace std;
typedef long long int ll;
const int N=1000010;
typedef pair<ll,ll> PII;
ll he[N],e[N],w[N],ne[N],idx=0;
ll n;
void add(ll x,ll y,ll z)
{
    e[idx]=y;
    w[idx]=z;
    ne[idx]=he[x];
    he[x]=idx++;
}
ll dij(ll lim)
{
    ll dist[N];
    ll vis[N];
    memset(dist,0x3f3f3f3f,sizeof(dist));
    memset(vis,0,sizeof(vis));
    priority_queue<PII,vector<PII>,greater<PII> > heap;
    dist[1]=0;
    heap.push({0,1});
    while(!heap.empty())
    {
        PII now =heap.top();
        heap.pop();
        ll dis=now.first,id=now.second;
        if(vis[id])
            continue;
        vis[id]=1;
        for(ll i=he[id];i!=-1;i=ne[i])
        {
            ll j=e[i];
            if(dist[j]>dis+w[i]&&w[i]<=lim)
            {
                dist[j]=dis+w[i];
                heap.push({dist[j],j});
            }

        }
    }

    return dist[n];

}
int main()
{
    ll m,ans,num,l,r,y,z,k,mid,i;
    double x,minn;
    scanf("%lld %lld %lf",&n,&m,&x);
    x=1.0+x/100.0;
    memset(he,-1,sizeof(he));
    for(i=1;i<=m;i++)
    {
        scanf("%lld %lld %lld",&k,&y,&z);
        add(k,y,z);
        add(y,k,z);
    }
    minn=dij(0x3f3f3f3f)*x;
    l=0;
    r=1e14;
    ans=0x3f3f3f3f;
    while(l<=r)
    {
        mid=(l+r)/2;
        num=dij(mid);
        if(num*1.0<=minn)
        {
            r=mid-1;
            ans=min(ans,mid);
        }
        else
            l=mid+1;
    }
    printf("%lld\n",ans);
    return 0;
}

这个题解说的可能不够全面,如果有问题可以直接私信我或者评论,我会及时看

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值