奢侈的旅行
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
题目大意: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;
}