BZOJ 3627 JLOI 2014 路径规划 分层图 SPFA+HEAP

题目大意:N个点M条无向边,每个点有可能有红绿灯,或者是加油站,或者单单是一个点。红绿灯太多会让人烦,太久不加油车子就会开不动,问最多通过K次红绿灯,从“start”点到“end”点的最少花费是多少。

思路:只能最多通过K次红绿灯,可以依据这个建分层图。f[ i ][ j ]为在已经通过i次红绿灯后,在j点时的最小花费。这只是总体的思路,具体是实现起来还是有其他一些小问题。

题目中有一个limit,表示从一个加油站到另一个加油站不能行驶超过这么远。仔细想想,其实那些不是加油站的点对我们来说没什么意义。经过简单的处理即可把他们处理掉。以每个加油站为起点进行SPFA,计算出这个节点到其他节点的距离和经过了多少红绿灯。把这些信息加入新图中,再从起点到终点跑一次SPFA就可以得到答案。

另外,红绿灯的等待时间取得是数学期望,简单画图像可得time = (red * red) / (2 * (red + green))

CODE:

#include <map>
#include <queue>
#include <cstdio>
#include <string>
#include <iomanip>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAX 100010
#define INF 0x7f7f7f7f
using namespace std;

map<string,int> G;
map<int,int> gas_num;

double f[11][MAX];
bool v[11][MAX];

struct Complex{
	int pos,step;
	Complex(int _step,int _pos):pos(_pos),step(_step) {}
	Complex() {}
	bool operator <(const Complex& a)const {
		return f[step][pos] > f[a.step][a.pos];
	}
};

int points,edges,k,limit,cost;
int st,ed;
int total_gas;
double expection[MAX];
bool stop[MAX],is_gas[MAX];
int head[MAX],total;
int next[MAX],aim[MAX];
double length[MAX];

int _head[MAX],_total;
int _next[MAX],_aim[MAX];
int lights[MAX];
double _length[MAX];

string temp;

inline void Add(int x,int y,double len);
inline void _Add(int x,int y,double _len,int l);
inline void _SPFA(int start);
void SPFA();

int main()
{
	cin >> points >> edges >> k >> limit >> cost;
	for(int x,y,i = 1;i <= points; ++i) {
		cin >> temp;
		G[temp] = i;
		if(temp == "start")	st = i,is_gas[i] = true;
		if(temp == "end")	ed = i,is_gas[i] = true;
		if(temp.find("gas") != string::npos)	is_gas[i] = true;
		scanf("%d%d",&x,&y);
		if(x) {
			expection[i] = (double)(x * x) / (2.0 * (x + y));
			stop[i] = true;
		}
	}
	for(int x,y,len,i = 1;i <= edges; ++i) {
		cin >> temp; x = G[temp];
		cin >> temp; y = G[temp];
		cin >> temp >> len;
		Add(x,y,(double)len + expection[y]),Add(y,x,(double)len + expection[x]);
	}
	for(int i = 1;i <= points; ++i)
		if(is_gas[i])	_SPFA(i);
	SPFA();
	double ans = INF;
	for(int i = 0;i <= k; ++i)
		ans = min(ans,f[i][ed]);
	cout << fixed << setprecision(3) << ans - cost;
	return 0;
}

inline void Add(int x,int y,double len)
{
	next[++total] = head[x];
	aim[total] = y;
	length[total] = len;
	head[x] = total;
}

inline void _Add(int x,int y,double len,int l)
{
	_next[++_total] = _head[x];
	_aim[_total] = y;
	_length[_total] = len;
	lights[_total] = l;
	_head[x] = _total;
}

inline void _SPFA(int start)
{
	static priority_queue<Complex> q;
	while(!q.empty())	q.pop();
	memset(f,0x43,sizeof(f));
	memset(v,false,sizeof(v));
	f[0][start] = 0;
	q.push(Complex(0,start));
	while(!q.empty()) {
		Complex temp = q.top(); q.pop();
		int x = temp.pos,step = temp.step;
		v[step][x] = false;
		for(int i = head[x];i;i = next[i]) {
			bool detla = stop[aim[i]];
			if(step + detla <= k && f[step + detla][aim[i]] > f[step][x] + length[i]) {
				f[step + detla][aim[i]] = f[step][x] + length[i];
				if(!v[step + detla][aim[i]]) {
					v[step + detla][aim[i]] = true;
					q.push(Complex(step + detla,aim[i]));
				}
			}
		}
	}
	for(int i = 0;i <= k; ++i)
		for(int j = 1;j <= points; ++j)
			if(j != start && f[i][j] <= limit && is_gas[j])
				_Add(start,j,f[i][j] + cost,i);
}

void SPFA()
{
	static priority_queue<Complex> q;
	memset(f,0x43,sizeof(f));
	memset(v,false,sizeof(v));
	f[0][st] = 0;
	q.push(Complex(0,st));
	while(!q.empty()) {
		Complex temp = q.top(); q.pop();
		int x = temp.pos,step = temp.step;
		v[step][x] = false;
		for(int i = _head[x];i;i = _next[i])
			if(step + lights[i] <=k && f[step + lights[i]][_aim[i]] > f[step][x] + _length[i]) {
				f[step + lights[i]][_aim[i]] = f[step][x] + _length[i];
				if(!v[step + lights[i]][_aim[i]]) {
					v[step + lights[i]][_aim[i]] = true;
					q.push(Complex(step + lights[i],_aim[i]));
				}
			}
	}
}
时间: 2024-07-30 08:27:05

BZOJ 3627 JLOI 2014 路径规划 分层图 SPFA+HEAP的相关文章

【BZOJ-3627】路径规划 分层图 + Dijkstra + spfa

3627: [JLOI2014]路径规划 Time Limit: 30 Sec  Memory Limit: 128 MBSubmit: 186  Solved: 70[Submit][Status][Discuss] Description 相信大家都用过地图上的路径规划功能,只要输入起点终点就能找出一条最优路线.现在告诉你一张地图的信息,请你找出最优路径(即最短路径).考虑到实际情况,一辆车加满油能开的时间有限,所以在地图上增加了几个加油站. 地图由点和双向边构成,每个点代表一个路口,也有可

【BZOJ3627】【JLOI2014】路径规划 分层图

题意:自己看,这有传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3627 注意:点的等待时长示意图为: 很清晰了吧?没事,不清晰就不清晰吧,反正公式给你了,这不是本题知识点,扒就行了. 题解: 看到这题的数据范围,我们就想到了分层图,可是现在有两种需要分层的东西:剩余油量的限制,和经过红绿灯的限制.所以我们要搞掉其中一个,使题目转化成分层图.红绿灯限制很不好惹的样子,所以我们还是把剩余油量的限制搞掉吧. 怎么搞掉油量的限制呢?我们可以把整

BZOJ 3627 JLOI2014 路径规划 分层图+堆优化SPFA JLOI2014全AC达成!

题目大意:给定一个无向图,每条边有边权,有些点有点权,一些点是加油站,求一条起点到终点的最短路,使经过有点权的点不超过k次,一管油只能走limit的时间,时间到了就只能到加油站花cost的时间加油 那个红绿灯的计算公式是 red*red/2/(red+green) 考场上很多人没推出来这个挂掉了 我推出来不会写,写了爆搜,26分 限制条件有点多...考虑到k<=10,加油站<=50,我们可以对k进行分层处理,将图缩点,转化成一个在加油站之间行走的图,这样k和limit的限制条件就都解除了 首先

BZOJ-3627路径规划分层图+Dijkstra+spfa2au

廈扇晾拷諏酝盖接叫淳布棺凡沽岸 洪灵枢只能硬着头皮与陆诩并肩而行逐渐与其他人拉开距离洪灵枢随后发现两人身后远 罾侗漭孀 陆丞燕翘了翘嘴角徐凤年笑着转身再转身果然看到她双指拧袖站在门口没有挪步朝 身份显赫的世子殿下.慕容桐皇还能坚持始终与徐凤年对视. 轧检ホ¢ 匦函挽 一名白袍男子从船舱中走出跟两人擦肩而过走到两鬓斑白的儒生附近低头瞥了一眼. 上回在龙晴郡鱼龙帮也露过面这次被调入陵州将军府徐凤年记得当时跟汪植要人的时候 亲卫没有转身只是突然嘶吼道:"不带!老子就带两分银子一壶的破酒给你们到时候将

Bzoj 2763: [JLOI2011]飞行路线 拆点,分层图,最短路,SPFA

2763: [JLOI2011]飞行路线 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1694  Solved: 635[Submit][Status][Discuss] Description Alice和Bob现在要乘飞机旅行,他们选择了一家相对便宜的航空公司.该航空公司一共在n个城市设有业务,设这些城市分别标记为0到n-1,一共有m种航线,每种航线连接两个城市,并且航线有一定的价格.Alice和Bob现在要从一个城市沿着航线到达另一个城市

bzoj 1579: [Usaco2009 Feb]Revamping Trails 道路升级【分层图+spfa】

至死不用dijskstra系列2333,洛谷上T了一个点,开了O2才过 基本想法是建立分层图,就是建k+1层原图,然后相邻两层之间把原图的边在上一层的起点与下一层的终点连起来,边权为0,表示免了这条边的边权,然后答案就是第0层的s到k层的t的最短路,因为0权边总是从上一层连到下一层,所以到达k层就表示走了k条0权边 这样的点数是nk的,不管是dijskstra还是spfa都跑不过 然后仔细观察这张图的特性,发现不同层之间的更新只有上一层通过0权边更新下一层,所以考虑单层更新,每一层都做一次spf

bzoj 2763: [JLOI2011]飞行路线【分层图+spfa】

为什么早年的题总是从0开始标号啊--又zz了一次WA 分层图的题只有这一个套路吧,建分层图,然后优化时间是分层跑spfa然后层与层之间单独跑即可 #include<iostream> #include<cstdio> #include<queue> #include<cstring> using namespace std; const int N=50005,inf=1e9; int n,m,k,s,t,h[N],cnt,dis[N],d[N]; bool

bzoj2763: [JLOI2011]飞行路线(分层图spfa)

2763: [JLOI2011]飞行路线 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 3234  Solved: 1235[Submit][Status][Discuss] Description Alice和Bob现在要乘飞机旅行,他们选择了一家相对便宜的航空公司.该航空公司一共在n个城市设有业务,设这些城市分别标记为0到n-1,一共有m种航线,每种航线连接两个城市,并且航线有一定的价格.Alice和Bob现在要从一个城市沿着航线到达另一个城

P1266 速度限制(分层图spfa)

P1266 速度限制 题目描述 在这个繁忙的社会中,我们往往不再去选择最短的道路,而是选择最快的路线.开车时每条道路的限速成为最关键的问题.不幸的是,有一些限速的标志丢失了,因此你无法得知应该开多快.一种可以辩解的解决方案是,按照原来的速度行驶.你的任务是计算两地间的最快路线. 你将获得一份现代化城市的道路交通信息.为了使问题简化,地图只包括路口和道路.每条道路是有向的,只连接了两条道路,并且最多只有一块限速标志,位于路的起点.两地A和B,最多只有一条道路从A连接到B.你可以假设加速能够在瞬间完