HDU-6290 奢侈的旅行 (Dijkstra+堆优化)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/chimchim04/article/details/90068314

奢侈的旅行

Problem Description

高玩小Q不仅喜欢玩寻宝游戏,还喜欢一款升级养成类游戏。在这个游戏的世界地图中一共有n个城镇,编号依次为1到n。

这些城镇之间有m条单向道路,第i 条单项道路包含四个参数ui,vi,ai,bi,表示一条从ui号城镇出发,在vi号城镇结束的单向道路,因为是单向道路,这不意味着小Q可以从vi沿着该道路走到ui。小Q的初始等级level为1,每当试图经过一条道路时,需要支付cost=log2level+ailevel点积分,并且经过该道路后,小Q的等级会提升ai级,到达level+ai级。但是每条道路都会在一定意义上歧视低消费玩家,准确地说,如果该次所需积分cost<bi,那么小Q不能经过该次道路,也不能提升相应的等级。

注意:本游戏中等级为正整数,但是积分可以是任意实数。

小Q位于1号城镇,等级为1,现在为了做任务要到n号城镇去。这将会是一次奢侈的旅行,请写一个程序帮助小Q找到需要支付的总积分最少的一条路线,或判断这是不可能的。

Input

第一行包含一个正整数T(1≤T≤30),表示测试数据的组数。

每组数据第一行包含两个整数n,m(2≤n≤100000,1≤m≤200000),表示城镇数和道路数。

接下来m行,每行四个整数ui,vi,ai,bi(1≤ui,vi≤n,ui≠vi,0≤ai≤109,0≤bi≤60),分别表示每条单向道路。

Output

对于每组数据,输出一行一个整数,即最少所需的总积分的整数部分,如:4.9999输出4,1.0输出1。若不存在合法路线请输出−1。

Sample Input

1 3 3 1 2 3 2 2 3 1 6 1 3 5 0

Sample Output

2

Source

"字节跳动杯"2018中国大学生程序设计竞赛-女生专场

题目大意:n个点,m条边,每条边 ui ,vi,ai ,bi 起点,终点,增加的等级,限制,问1-n最小消耗的积分

思路:每次走过一条路i 的消费是 log2(( level i +ai)/(level i) )  式子可以转化为log2( ai  +  level i) - log2( level i),所以每次的消费就是log2( ai  +  level i) - log2( level i),如果走两条路,从1到v1再到v2 :那么消费就是

 log2(a1+ level1) - log2( level 1)+log2(a2+ level2)-log2(level2), 因为level2就是level1+a1,所以可以化简为

- log2( level 1)+log2(a2+ level2),如果把这个式子扩长,可以发现中间的部分都可以通过一加一减化掉,只剩下

-log2(1)+log2(level n) 因为log2(1)==0 所以只要求得到n时的最小等级leveln,对其求log2(level n)就是结果

最小等级就可以直接用Dijkstra求最短路求得

代码:

#include<stdio.h>
#include<string.h>
#include<math.h>
#include<queue>
#include<algorithm>
using namespace std;
#define ll long long
const int N=200005;
const ll inf=(ll)1<<61;
struct qnode
{
    int v;
    ll c;
    qnode(int _v=0,ll _c=0):v(_v),c(_c) {}
    bool operator<(const qnode &r)const
    {
        return c>r.c;
    }
} no;
struct node
{
    ll a;
    int v,nex,b;
} e[N];
int n,m,tot,f[N],vis[N];
ll dis[N],bb[70];
void add(int u,int v,ll a,int b)
{
    e[tot].v=v,e[tot].a=a,e[tot].b=b;
    e[tot].nex=f[u];
    f[u]=tot++;
    //printf("%d %d\n",tot-1,v);
}
void dij()
{
    for(int i=0; i<=n; i++)
    {
        vis[i]=0;
        dis[i]=inf;
    }
    priority_queue<qnode>q;
    dis[1]=1;
    q.push(qnode(1,1));
    while(!q.empty())
    {
        no=q.top();
        q.pop();
        int u=no.v;
        if(vis[u]) continue;
        vis[u]=1;
        //printf("%d %lld\n",u,dis[u]);
        for(int i=f[u]; i!=-1; i=e[i].nex)
        {
            int v=e[i].v;
            //printf("   %d\n",v);
            ll a=e[i].a,b=bb[e[i].b];
            if(a/dis[u]+1<b) continue;
            if(dis[v]>a+dis[u])
            {
                dis[v]=a+dis[u];
                q.push(qnode(v,dis[v]));
            }
        }
    }
    //printf("%lld\n",dis[n]);
    if(dis[n]>=inf) printf("-1\n");
    else
    {
        double x=log2(dis[n]);
        printf("%d\n",(int)x);
    }
}
int main()
{
    bb[0]=1;
    for(int i=1;i<=60;i++)
        bb[i]=(ll)bb[i-1]*(ll)2;
    int t;
    scanf("%d",&t);
    while(t--)
    {
        tot=0;
        scanf("%d%d",&n,&m);
        memset(f,-1,sizeof(f));
        int u,v,b;
        ll a;
        for(int i=0; i<m; i++)
        {
            scanf("%d %d %lld %d",&u,&v,&a,&b);
            add(u,v,a,b);
        }
        dij();
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/chimchim04/article/details/90068314