最短路:HDU6290

 

奢侈的旅行

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


 

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

由于今年还有女生赛,然后就去看了看我们去年打的女生赛的题,正好在写最短路,然后想到去年这个时候我们什么算法都不会,只会不用算法的签到题,幸运苟了一个铜末,今年再来看题目觉得自己稍微有一点点长进。这题我也就改了十几遍吧,怎么都找不到bug,然后无奈之下找了别人的代码来对拍,发现我少了个初始化。嗯我是zz。

这题就是一个很简单的dijkstra最短路堆优化,然后利用题目信息将数据进行化简,发现其实就是一道最短路题再把最终结果取个log2就好了。

 

 

#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
#include <cmath>
using namespace std;
const int MAXN=200005;
const long long INF=1ll << 60;
int n, m;
long long p[61];
struct qnode{
	int v;
	long long a;
	int b;
	qnode(int _v=0,long long _a = 0):v(_v),a(_a){}
	bool operator <(const qnode &r)const{
		return a > r.a;
	}
};
struct Edge{
	int v;
	long long a;
	int b;
	Edge(int _v=0,long long _a=0, int _b = 0):v(_v),a(_a),b(_b){}
};
vector<Edge>E[MAXN];
bool vis[MAXN];
long long dist[MAXN];
void Dijkstra(int n,int start){
	memset(vis,false,sizeof(vis));
	for(int i=1;i<=n;i++) dist[i]=INF;
	priority_queue<qnode>que;
	while(!que.empty()) que.pop();
	dist[start]=1;
	que.push(qnode(start,1));
	qnode tmp;
	while(!que.empty()){
		tmp=que.top();
		que.pop();
		int u=tmp.v;
		if(vis[u])continue;
		vis[u]=true;
		for(int i = 0; i < E[u].size(); i++){
			int v = E[u][i].v;
			if(1 + E[u][i].a / dist[u] < p[E[u][i].b]) continue;
			if(dist[v] > dist[u] + E[u][i].a)
			{
				dist[v] = dist[u] + E[u][i].a;
				que.push(qnode(v,dist[v]));
			}
		}
	}
}
void addedge(int u,int v,long long w1, int w2){
	E[u].push_back(Edge(v,w1, w2));
}
int main()
{
	//freopen("test2.in","w",stdout);
	p[0] = 1;
	for(int i = 1; i < 61; i++) p[i] = p[i-1] * 2;
	int T;
	scanf("%d", &T);
	while(T--)
	{
		scanf("%d%d", &n, &m);
		for(int i = 0; i <= n; i++) E[i].clear();
		for(int i = 0; i < m; i++)
		{
			int u, v;
			long long a1;
			int b1;
			scanf("%d%d%lld%d", &u, &v, &a1, &b1);
			addedge(u, v, a1, b1);
		}
		Dijkstra(n, 1); 
		if(dist[n] == INF) printf("-1\n");
		else printf("%.0f\n", floor(log2(dist[n])));
	}
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值