奢侈的旅行
Time Limit: 14000/7000 MS (Java/Others) Memory Limit: 512000/512000 K (Java/Others)Total Submission(s): 445 Accepted Submission(s): 86
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
1 3 3 1 2 3 2 2 3 1 6 1 3 5 0
Sample Output
2
Source
条件为 log2 [ (level+a[i]) /(level) ]>= b[i] 转化一下为 [ (level+a[i]) /(level) ] >= 2^b[i]
对于 log 函数 有 log a + log b = log ab
所以路径的最终结果为 log2(1+a1+a2+a3+….an)
对于 路径而言 就是一个最短路, 但是 数据很强, 会卡spfa 超时,
所以 用 堆优化的 dijstra.
123
Code
#include <iostream>
#include <bits/stdc++.h>
#define debug cout<<"Debug"<<endl;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int MAXN = 4e5+10;
using namespace std;
int n,m;
int head[MAXN];
ll dis[MAXN];
int vis[MAXN];
int cot;
struct node{
int v,a,b,next;
}edge[MAXN];
void init(){cot = 0; memset(head,-1,sizeof(head));}
void add(int u,int v,int a,int b)
{
edge[++cot].v = v ;
edge[cot].a = a;
edge[cot].b = b;
edge[cot].next = head[u];
head[u] = cot;
}
struct Node{
int id;
ll level;
friend bool operator <(const Node p1,const Node p2)
{
return p1.level > p2.level ; // 小的先出来
}
};
void dijstra()
{
priority_queue<Node>Q;
Q.push(Node{1,1});
memset(dis,inf,sizeof(dis));
memset(vis,0,sizeof(vis));
dis[1] = 1;
while(!Q.empty())
{
Node u = Q.top();
Q.pop();
int tid = u.id;
if(tid == n)
{
for(int i = 1;;i++)
{
if( (1ll<<i) > u.level)
{
printf("%d\n",i-1);
return ;
}
}
}
if(vis[tid])
continue;
vis[tid] = 1;
for( int i = head[tid] ; i!= -1 ;i = edge[i].next)
{
int v = edge[i].v;
if(vis[v])
continue;
if( ( (u.level + edge[i].a)/(u.level) ) >= (1ll<<edge[i].b) && dis[v] > (u.level+edge[i].a))
{
//debug;
dis[v] = u.level+edge[i].a;
Node p;
p.id = v;
p.level = dis[v];
Q.push(p);
}
}
}
// debug;
printf("-1\n");
}
int main()
{
ios_base::sync_with_stdio(false);
cout.setf(ios::fixed);
cout.tie(nullptr);
cin.tie(nullptr);
int t;
cin>>t;
while(t--)
{
init();
cin>>n>>m;
while(m--)
{
int x,y,a,b;
cin>>x>>y>>a>>b;
add(x,y,a,b);
}
dijstra();
}
return 0;
}