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

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

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

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

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

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

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

接下来mm行,每行四个整数ui,vi,ai,bi(1ui,vin,uivi,0ai109,0bi60)ui,vi,ai,bi(1≤ui,vi≤n,ui≠vi,0≤ai≤109,0≤bi≤60),分别表示每条单向道路。
Output对于每组数据,输出一行一个整数,即最少所需的总积分的整数部分,如:4.99994.9999输出44,1.01.0输出11。若不存在合法路线请输出1−1。Sample Input

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

Sample Output

2


 

题意:

给你n个点,m条边,每条边有u,v,a,b这四个值,初始等级为1.问你从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求最短路求得

思路参考链接:https://blog.csdn.net/chimchim04/java/article/details/90068314
 
 

我的出错点1:

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
#include<math.h>
using namespace std;
const int INF=0x3f3f3f3f;
const int maxn=2e5+5;
typedef long long ll;
const ll MAX=1e17;
const ll inf=(ll)1<<61;
struct shudui1
{
    ll start,value;
    bool operator < (const shudui1 q)const
    {
        return value>q.value; //最短路模板中这里应该是大于号,我写成了小于号
    }
} str1;

下面代码就是这个原因错的:

  1 #include<stdio.h>
  2 #include<string.h>
  3 #include<iostream>
  4 #include<algorithm>
  5 #include<queue>
  6 #include<vector>
  7 #include<math.h>
  8 using namespace std;
  9 const int INF=0x3f3f3f3f;
 10 const int maxn=2e5+5;
 11 typedef long long ll;
 12 const ll MAX=1e17;
 13 const ll inf=(ll)1<<61;
 14 struct shudui1
 15 {
 16     ll start,value;
 17     bool operator < (const shudui1 q)const
 18     {
 19         return value<q.value;
 20     }
 21 } str1;
 22 struct node
 23 {
 24     ll a,v,nex,b;
 25 } e[maxn];
 26 ll tot,v[maxn],p[70],vis[maxn],head[maxn];
 27 void add(ll u,ll v,ll a,ll b)
 28 {
 29     e[tot].v=v,e[tot].a=a,e[tot].b=b;
 30     e[tot].nex=head[u];
 31     head[u]=tot++;
 32     //printf("%d %d\n",tot-1,v);
 33 }
 34 priority_queue<shudui1>r; //里面的数据默认是从小到大排序,这样就不用通过for循环遍历在每一次找v里面的最小值,可以直接找到最小值,减少代码运行次数
 35 void JK(ll s)
 36 {
 37     v[s]=1;
 38     str1.start=s;
 39     str1.value=1;
 40     r.push(str1);
 41     while(!r.empty())
 42     {
 43 
 44         ll x,y;
 45         str1=r.top();
 46         r.pop();
 47         x=str1.start;
 48         y=str1.value;
 49         //printf("%lld***\n",x);
 50         if(vis[x]) continue;
 51         vis[x]=1;
 52         //printf("**%lld\n",len);
 53         for(ll i=head[x]; i!=-1; i=e[i].nex)
 54         {
 55 
 56             ll vv=e[i].v,a=e[i].a,b=e[i].b;
 57             ll temp=1+a/v[x];
 58             //printf("%lld %lld\n",temp,p[b]);
 59             if(temp<p[b]) continue;
 60             //printf("%lld %lld\n",v[x]+v,v[vv]);
 61             if((v[x]+a<v[vv]))
 62             {
 63                 //printf("**");
 64                 v[vv]=v[x]+a;
 65                 str1.start=vv;
 66                 str1.value=v[vv];
 67                 r.push(str1);
 68             }
 69         }
 70     }
 71 }
 72 int main()
 73 {
 74 //    double xx=1.99;
 75 //    printf("%.0lf\n",xx);
 76     ll t;
 77     p[0]=1;
 78     for(ll i=1; i<=60; ++i)
 79         p[i]=(ll)p[i-1]*(ll)2;
 80     scanf("%lld",&t);
 81     while(t--)
 82     {
 83         memset(head,-1,sizeof(head));
 84         tot=0;
 85         ll n,m;
 86         scanf("%lld%lld",&n,&m);
 87         for(ll i=1; i<=n; ++i)
 88             v[i]=inf,vis[i]=0;
 89         while(m--)
 90         {
 91             ll x,y,z1,z2;
 92             scanf("%lld%lld%lld%lld",&x,&y,&z1,&z2);
 93             add(x,y,z1,z2);
 94         }
 95         JK(1);
 96         if(v[n]>=inf) printf("-1\n");
 97         else
 98         {
 99             double x=log2(v[n]);
100             printf("%lld\n",(ll)x);
101         }
102     }
103     return 0;
104 }
View Code

 

出错点2:

while(!r.empty())
    {

        ll x,y;
        str1=r.top();
        r.pop();
        x=str1.start;
        y=str1.value;
        //printf("%lld***\n",x);
        if(vis[x]) continue;
        vis[x]=1;
        //printf("**%lld\n",len);
        for(ll i=head[x]; i!=-1; i=e[i].nex)
        {

            ll vv=e[i].v,a=e[i].a,b=e[i].b;
            ll temp=1+a/v[x];  //最短路算法里面这里应该是除于v[x],我却写成了str1.value
            //printf("%lld %lld\n",temp,p[b]);
            if(temp<p[b]) continue;
            //printf("%lld %lld\n",v[x]+v,v[vv]);
            if((v[x]+a<v[vv]))
            {
                //printf("**");
                v[vv]=v[x]+a;
                str1.start=vv;
                str1.value=v[vv];
                r.push(str1);
            }
        }
    }

 

原代码:

  1 #include<stdio.h>
  2 #include<string.h>
  3 #include<iostream>
  4 #include<algorithm>
  5 #include<queue>
  6 #include<vector>
  7 #include<math.h>
  8 using namespace std;
  9 const int INF=0x3f3f3f3f;
 10 const int maxn=2e5+5;
 11 typedef long long ll;
 12 const ll MAX=1e17;
 13 const ll inf=(ll)1<<61;
 14 struct shudui1
 15 {
 16     ll start,value;
 17     bool operator < (const shudui1 q)const
 18     {
 19         return value>q.value;  //这里是大于号
 20     }
 21 } str1;
 22 struct node
 23 {
 24     ll a,v,nex,b;
 25 } e[maxn];
 26 ll tot,v[maxn],p[70],vis[maxn],head[maxn];
 27 void add(ll u,ll v,ll a,ll b)
 28 {
 29     e[tot].v=v,e[tot].a=a,e[tot].b=b;
 30     e[tot].nex=head[u];
 31     head[u]=tot++;
 32     //printf("%d %d\n",tot-1,v);
 33 }
 34 priority_queue<shudui1>r; //里面的数据默认是从小到大排序,这样就不用通过for循环遍历在每一次找v里面的最小值,可以直接找到最小值,减少代码运行次数
 35 void JK(ll s)
 36 {
 37     v[s]=1;
 38     str1.start=s;
 39     str1.value=1;
 40     r.push(str1);
 41     while(!r.empty())
 42     {
 43 
 44         ll x,y;
 45         str1=r.top();
 46         r.pop();
 47         x=str1.start;
 48         y=str1.value;
 49         //printf("%lld***\n",x);
 50         if(vis[x]) continue;
 51         vis[x]=1;
 52         //printf("**%lld\n",len);
 53         for(ll i=head[x]; i!=-1; i=e[i].nex)
 54         {
 55 
 56             ll vv=e[i].v,a=e[i].a,b=e[i].b;
 57             ll temp=1+a/v[x];//最短路算法里面这里应该是除于v[x],我却写成了str1.value
 58             //printf("%lld %lld\n",temp,p[b]);
 59             if(temp<p[b]) continue;
 60             //printf("%lld %lld\n",v[x]+v,v[vv]);
 61             if((v[x]+a<v[vv]))
 62             {
 63                 //printf("**");
 64                 v[vv]=v[x]+a;
 65                 str1.start=vv;
 66                 str1.value=v[vv];
 67                 r.push(str1);
 68             }
 69         }
 70     }
 71 }
 72 int main()
 73 {
 74 //    double xx=1.99;
 75 //    printf("%.0lf\n",xx);
 76     ll t;
 77     p[0]=1;
 78     for(ll i=1; i<=60; ++i)
 79         p[i]=(ll)p[i-1]*(ll)2;
 80     scanf("%lld",&t);
 81     while(t--)
 82     {
 83         memset(head,-1,sizeof(head));
 84         tot=0;
 85         ll n,m;
 86         scanf("%lld%lld",&n,&m);
 87         for(ll i=1; i<=n; ++i)
 88             v[i]=inf,vis[i]=0;
 89         while(m--)
 90         {
 91             ll x,y,z1,z2;
 92             scanf("%lld%lld%lld%lld",&x,&y,&z1,&z2);
 93             add(x,y,z1,z2);
 94         }
 95         JK(1);
 96         if(v[n]>=inf) printf("-1\n");
 97         else
 98         {
 99             double x=log2(v[n]);
100             printf("%lld\n",(ll)x);
101         }
102     }
103     return 0;
104 }
View Code

 

 

整理之后的代码:

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<iostream>
 4 #include<algorithm>
 5 #include<queue>
 6 #include<vector>
 7 #include<math.h>
 8 using namespace std;
 9 const int INF=0x3f3f3f3f;
10 const int maxn=2e5+5;
11 typedef long long ll;
12 const ll MAX=1e17;
13 const ll inf=(ll)1<<61;
14 struct shudui1
15 {
16     ll v,c;
17     shudui1(ll x=0,ll y=0):v(x),c(y) {}
18     bool operator < (const shudui1 q)const
19     {
20         return c>q.c;
21     }
22 } str1;
23 struct node
24 {
25     ll a,v,nex,b;
26 } e[maxn];
27 ll tot,dis[maxn],p[70],vis[maxn],head[maxn];
28 void add(ll u,ll v,ll a,ll b)
29 {
30     e[tot].v=v,e[tot].a=a,e[tot].b=b;
31     e[tot].nex=head[u];
32     head[u]=tot++;
33     //printf("%d %d\n",tot-1,v);
34 }
35 priority_queue<shudui1>r; //里面的数据默认是从小到大排序,这样就不用通过for循环遍历在每一次找v里面的最小值,可以直接找到最小值,减少代码运行次数
36 void JK(ll s,ll n)
37 {
38 
39     dis[s]=1;
40     str1.v=s;
41     str1.c=1;
42     r.push(str1);
43     while(!r.empty())
44     {
45         str1=r.top();
46         r.pop();
47         int u=str1.v;
48         if(vis[u]) continue;
49         vis[u]=1;
50         //printf("%d %lld\n",u,dis[u]);
51         for(int i=head[u]; i!=-1; i=e[i].nex)
52         {
53             int v=e[i].v;
54             //printf("   %d\n",v);
55             ll a=e[i].a,b=p[e[i].b];
56             if(a/dis[u]+1<b) continue;
57             if(dis[v]>a+dis[u])
58             {
59                 dis[v]=a+dis[u];
60                 r.push(shudui1(v,dis[v]));
61             }
62         }
63     }
64     if(dis[n]>=inf) printf("-1\n");
65     else
66     {
67         double x=log2(dis[n]);
68         printf("%d\n",(int)x);
69     }
70 }
71 int main()
72 {
73     ll n,m;
74     p[0]=1;
75     for(ll i=1; i<=60; i++)
76         p[i]=(ll)p[i-1]*(ll)2;
77     ll t;
78     scanf("%lld",&t);
79     while(t--)
80     {
81         tot=0;
82         scanf("%lld%lld",&n,&m);
83         for(ll i=0; i<=n; i++)
84         {
85             vis[i]=0;
86             dis[i]=inf;
87         }
88         memset(head,-1,sizeof(head));
89         ll x,y,b,a;
90         for(ll i=0; i<m; i++)
91         {
92             scanf("%lld %lld %lld %lld",&x,&y,&a,&b);
93             add(x,y,a,b);
94         }
95         JK(1,n);
96     }
97     return 0;
98 }
View Code

 

posted @ 2020-04-15 22:33  kongbursi  阅读(160)  评论(0编辑  收藏  举报