HDU-6290:奢侈的旅行(最短路)

奢侈的旅行

                                                               Time Limit: 14000/7000 MS (Java/Others)    Memory Limit: 512000/512000 K (Java/Others)
                                                                                          Total Submission(s): 592    Accepted Submission(s): 121


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

这些城镇之间有 m 条单向道路,第 i  条单项道路包含四个参数ui ,vi,ai,bi ,表示一条从 ui 号城镇出发,在 vi 号城镇结束的单向道路,因为是单向道路,这不意味着小Q可以从 vi 沿着该道路走到 ui 。小Q的初始等级 level 1 ,每当试图经过一条道路时,需要支付 cost=log2((level+ai)/level) 点积分,并且经过该道路后,小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<=10^9,0<=bi<=60), 分别表示每条单向道路。
 

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

Sample Input
 
  
13 31 2 3 22 3 1 61 3 5 0
 

Sample Output
 
  
2


思路:仔细观察那个cost的公式,所有的cost相加之后,利用对数公式log(x*y)=log(x)+log(y),可以发现cost=log(终点的等级)。所以只需要到达终点的时候,等级尽可能的低就行了,那么就是堆优化的最短路了。

#include<bits/stdc++.h>
using namespace std;
const int MAX=2e5+10;
typedef long long ll;
struct lenka
{
    ll x,le;
    int operator<(const lenka& q)const{return q.le<le;}
};
struct EDG
{
    int to,next,a,b;
}ed[MAX];
int head[MAX],tot;
ll d[MAX];
void add(int x,int y,int a,int b)
{
    ed[tot].to=y;
    ed[tot].a=a;
    ed[tot].b=b;
    ed[tot].next=head[x];
    head[x]=tot++;
}
void bfs()
{
    d[1]=1;
    priority_queue<lenka>p;
    p.push((lenka){1,1});
    while(!p.empty())
    {
        lenka now=p.top();p.pop();
        if(now.le!=d[now.x])continue;
        for(int i=head[now.x];i!=-1;i=ed[i].next)
        {
            int nex=ed[i].to;
            if((1ll<<ed[i].b)>1+ed[i].a/now.le)continue;//没有了精度误差的问题
            if(d[nex]!=-1&&d[nex]<=now.le+ed[i].a)continue;
            d[nex]=now.le+ed[i].a;
            p.push((lenka){nex,d[nex]});
        }
    }
}
int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        int n,m;
        scanf("%d%d",&n,&m);
        tot=0;
        for(int i=1;i<=n;i++)head[i]=-1;
        while(m--)
        {
            int x,y,a,b;
            scanf("%d%d%d%d",&x,&y,&a,&b);
            add(x,y,a,b);
        }
        for(int i=1;i<=n;i++)d[i]=-1;
        bfs();
        for(int i=0;i<=62;i++)
        {
            if((1ll<<i)>d[n])//没有了精度误差的问题
            {
                printf("%d\n",i-1);
                break;
            }
        }
    }
    return 0;
}


猜你喜欢

转载自blog.csdn.net/mitsuha_/article/details/80740644