Charles in Charge Gym - 101490E (隊列優化dij+二分)

https://vjudge.net/contest/350975#problem/E

 

題意:給一張無向圖,求一條從1到n路上的最大邊,使得其最小,同時還要滿足 這條路長度<=最短路*(1+X%)

 

先跑一邊最短路,求出最短路

然後二分答案,求在最大邊爲mid的情況下的最短路(在鬆弛的時候判斷一下邊大於mid就不鬆弛),用spfa T了,

得用隊列優化dij

#include<bits/stdc++.h>
using namespace std;
const long long maxn = 100009;
typedef pair<long long,long long > pii;

struct node
{
    long long to,next;
    double w;
} edge[maxn<<1];

double per,minn,tot;
long long ans;

long long head[maxn<<1],flag[maxn],n,cnt,dis[maxn];

void add(long long u,long long v,double w)
{
    edge[cnt].w = w;
    edge[cnt].to = v;
    edge[cnt].next = head[u];
    head[u] =  cnt ++;
}

long long dij(long long s,long long t,long long lim)
{
    memset(dis,0x3f3f3f3f,sizeof(dis));
    priority_queue<pii,vector<pii>,greater<pii> > que;
    dis[s] = 0;
    que.push(make_pair(0,s));
    while(!que.empty())
    {
        pii p =que.top();
        que.pop();
        if(dis[p.second]<p.first)
        {
            continue;
        }
        for(long long i = head[p.second]; i != -1; i = edge[i].next)
        {
            long long to = edge[i].to;
            if(dis[to]>dis[p.second]+edge[i].w&&edge[i].w<=lim)
            {
                dis[to] = dis[p.second]+edge[i].w;
                que.push(make_pair(dis[to],to));
            }
        }

    }
    return dis[t];
}


int main()
{
    long long i,j,m,a,b,c,l,r,num,ans;
    memset(head,-1,sizeof(head));
    scanf("%lld %lld %lf",&n,&m,&per);
    per = 1.0+per/100.0;
    for(i = 0; i < m; i++)
    {
        scanf("%lld %lld %lld",&a,&b,&c);
        add(a,b,c);
        add(b,a,c);
    }
    minn = dij(1,n,0x3f3f3f3f);
    l = 0;
    r = 1e14;
    ans = 0x3f3f3f3f;
    while(l<=r)
    {
        long long mid = (l+r)/2;
        num = dij(1,n,mid);

        if(num*1.0<= minn*per)
        {
            r = mid-1;
            ans = min(ans,mid);
        }
        else
            l = mid+1;
    }
    printf("%lld\n",ans);
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章