版权声明:Why is everything so heavy? https://blog.csdn.net/lzc504603913/article/details/80524386
奢侈的旅行
Time Limit: 14000/7000 MS (Java/Others) Memory Limit: 512000/512000 K (Java/Others)Total Submission(s): 189 Accepted Submission(s): 34
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找到需要支付的总积分最少的一条路线,或判断这是不可能的。
这些城镇之间有 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),分别表示每条单向道路。
每组数据第一行包含两个整数 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
13 31 2 3 22 3 1 61 3 5 0
Sample Output
2
Source
Recommend
liuyiding
解题思路:很容易想到最短路,关键是cost的计算,对于任意一条路径,他的花费总和 log2((1+a1)/1)+log2((1+a1+a2)/(1+a1))+log2((1+a1+a2+a3)/(1+a1+a2)) 。然后通过对数公式,可以化简为 log2(1+Sn)。那么就可以计算cost了,然后再求最短路径的时候,把限制条件加上去即可。用SPFA一直超时,改成堆优化迪杰斯特拉就过了。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXM=200500;
const int MAXN=100500;
inline void scan_d(int &ret)
{
char c;
ret = 0;
while ((c = getchar()) < '0' || c > '9');
while (c >= '0' && c <= '9')
{
ret = ret * 10 + (c - '0'), c = getchar();
}
}
struct edge{
int u;
int v;
int a;
int b;
int next;
}e[MAXM];
int edge_num,head[MAXN];
void insert_edge(int u,int v,int a,int b){
e[edge_num].u=u;
e[edge_num].v=v;
e[edge_num].a=a;
e[edge_num].b=b;
e[edge_num].next=head[u];
head[u]=edge_num++;
}
struct Node{
int id;
ll d;
Node(int id, ll d):id(id),d(d){}
bool operator < (const Node &A)const{
return d > A.d;
}
};
ll d[MAXN];
bool vis[MAXN];
int dijkstra(int S,int T){
memset(d,0x3f,sizeof(d));
memset(vis,0,sizeof(vis));
priority_queue<Node> que;
que.push(Node(S,1));
d[S]=1;
while(!que.empty()){
Node tp1=que.top();
que.pop();
int tp=tp1.id;
if(tp==T){
for(int i=1;;i++)
if((1LL<<i)>tp1.d)
return i-1;
}
if(vis[tp])
continue;
vis[tp]=1;
for(int i=head[tp];i!=-1;i=e[i].next){
if(vis[e[i].v])
continue;
if(((e[i].a+tp1.d)/(tp1.d))>=(1LL<<e[i].b)&&e[i].a+tp1.d<d[e[i].v]){
d[e[i].v]=e[i].a+tp1.d;
que.push(Node(e[i].v,d[e[i].v]));
}
}
}
return -1;
}
int main()
{
int T;
scan_d(T);
while(T--){
memset(head,-1,sizeof(head));
edge_num=0;
int u,v,a,b;
int N,M;
scan_d(N);
scan_d(M);
for(int i=0;i<M;i++){
scan_d(u);
scan_d(v);
scan_d(a);
scan_d(b);
insert_edge(u,v,a,b);
}
printf("%d\n",dijkstra(1,N));
}
return 0;
}