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

题目大意:给定一个无向图,每条边有边权,有些点有点权,一些点是加油站,求一条起点到终点的最短路,使经过有点权的点不超过k次,一管油只能走limit的时间,时间到了就只能到加油站花cost的时间加油

那个红绿灯的计算公式是 red*red/2/(red+green) 考场上很多人没推出来这个挂掉了 我推出来不会写,写了爆搜,26分

限制条件有点多。。。考虑到k<=10,加油站<=50,我们可以对k进行分层处理,将图缩点,转化成一个在加油站之间行走的图,这样k和limit的限制条件就都解除了

首先我们枚举每一个加油站(起始点和出发点看作加油站),以加油站为起点跑一遍SPFA,然后向其它加油站加长度不超过limit的直连边,这样加油站以外的点就可以去死了

然后以起始点为源再跑一遍SPFA就可以了

交的人好少好少好少。。。我这烂代码都排了第二。。因为一共就两个人交。。。

10W的SPFA跑50遍 我怕超时用了堆优化 不用堆优化可能会死 気をつけて

#include<map>
#include<string>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define M 10100
using namespace std;
map<string,int>a;
string st;
struct abcd{
	int to,lights,next;
	bool usable;
	double f;
}table[100100];
int head[M],tot,top;
int n,m,k,cnt,s,t;
double limit,cost,light[M];
bool is_gasonline_stand[M];
int gasonline_stands[100];
double f[M][11],ans=2147483647;
pair<int,int>heap[M*10];
int pos[M][11];

void pop();
void push_up(int t);
void SPFA(int from);
void insert(pair<int,int>x);
void add(int x,int y,double z);
void Final_SPFA()
{
	int i;
	memset(f,0x42,sizeof f);
	insert( make_pair(s,0) );
	f[s][0]=0;
	while(top)
	{
		pair<int,int>x=heap[1];pop();
		for(i=head[x.first];i;i=table[i].next)
			if( table[i].usable )
				if( x.second+table[i].lights<=k && f[x.first][x.second]+table[i].f<f[table[i].to][x.second+table[i].lights] )
				{
					f[table[i].to][x.second+table[i].lights]=f[x.first][x.second]+table[i].f;
					if( !pos[table[i].to][x.second+table[i].lights] )
						insert( make_pair( table[i].to , x.second+table[i].lights ) );
					else
						push_up( pos[table[i].to][x.second+table[i].lights] );
				}
	}
	for(i=0;i<=k;i++)
		ans=min(ans,f[t][i]);
}

int main()
{
	int i,x,y;
	double z,green,red;
	cin>>n>>m>>k>>limit>>cost;
	for(i=1;i<=n;i++)
	{
		cin>>st;
		scanf("%lf%lf",&red,&green);

		a[st]=++cnt;
		if(st=="start")
			s=i,gasonline_stands[++gasonline_stands[0]]=i;
		else if(st=="end")
			t=i,gasonline_stands[++gasonline_stands[0]]=i;
		else if( ~st.find("gas") )
			is_gasonline_stand[i]=1,gasonline_stands[++gasonline_stands[0]]=i;

		if(red==0)
			light[i]=0;
		else
			light[i]=red*red/2.0/(red+green);
	}
	for(i=1;i<=m;i++)
	{
		cin>>st;x=a[st];
		cin>>st;y=a[st];
		cin>>st;scanf("%lf",&z);
		add(x,y,z);
		add(y,x,z);
	}
	for(i=1;i<=gasonline_stands[0];i++)
		SPFA(gasonline_stands[i]);
	Final_SPFA();
	printf("%.3lf\n",ans-cost);
}

void add(int x,int y,double z)
{
	table[++tot].to=y;
	table[tot].lights=light[x]?1:0;
	table[tot].f=z+light[x];
	table[tot].next=head[x];
	head[x]=tot;
}
void push_up(int t)
{
	while( t>1 && f[heap[t].first][heap[t].second]<f[heap[t>>1].first][heap[t>>1].second] )
		swap(heap[t],heap[t>>1]),swap(pos[heap[t].first][heap[t].second],pos[heap[t>>1].first][heap[t>>1].second]),t>>=1;
}
void insert(pair<int,int>x)
{
	heap[++top]=x;
	pos[x.first][x.second]=top;
	push_up(top);
}
void pop()
{
	pos[heap[1].first][heap[1].second]=0;
	heap[1]=heap[top];
	heap[top--]=heap[0];
	pos[heap[1].first][heap[1].second]=1;
	int t=2;
	while(t<=top)
	{
		if( t<top && f[heap[t].first][heap[t].second]>f[heap[t+1].first][heap[t+1].second] )
			t++;
		if( f[heap[t].first][heap[t].second]<f[heap[t>>1].first][heap[t>>1].second] )
			swap(heap[t],heap[t>>1]),swap(pos[heap[t].first][heap[t].second],pos[heap[t>>1].first][heap[t>>1].second]),t<<=1;
		else
			break;
	}
}
void SPFA(int from)
{
	int i,j;
	memset(f,0x42,sizeof f);
	insert( make_pair(from,0) );
	f[from][0]=0;
	while(top)
	{
		pair<int,int>x=heap[1];pop();
		for(i=head[x.first];i;i=table[i].next)
			if(!table[i].usable)
				if( x.second+table[i].lights<=k && f[x.first][x.second]+table[i].f<f[table[i].to][x.second+table[i].lights] && f[x.first][x.second]+table[i].f<=limit )
				{
					f[table[i].to][x.second+table[i].lights]=f[x.first][x.second]+table[i].f;
					if( !pos[table[i].to][x.second+table[i].lights] )
						insert( make_pair( table[i].to , x.second+table[i].lights ) );
					else
						push_up( pos[table[i].to][x.second+table[i].lights] );
				}
	}
	for(i=1;i<=gasonline_stands[0];i++)
	{
		if(gasonline_stands[i]==from)
			continue;
		for(j=0;j<=k;j++)
			if(f[ gasonline_stands[i] ][j]<=limit)
				add( from , gasonline_stands[i] , f[ gasonline_stands[i] ][j]+cost ),table[tot].lights=j,table[tot].usable=1;
	}
}
时间: 2024-07-30 08:27:09

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

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

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

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

题目大意:N个点M条无向边,每个点有可能有红绿灯,或者是加油站,或者单单是一个点.红绿灯太多会让人烦,太久不加油车子就会开不动,问最多通过K次红绿灯,从"start"点到"end"点的最少花费是多少. 思路:只能最多通过K次红绿灯,可以依据这个建分层图.f[ i ][ j ]为在已经通过i次红绿灯后,在j点时的最小花费.这只是总体的思路,具体是实现起来还是有其他一些小问题. 题目中有一个limit,表示从一个加油站到另一个加油站不能行驶超过这么远.仔细想想,其实那些

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

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

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

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

【bzoj3073】[Pa2011]Journeys 线段树优化建图+堆优化Dijkstra

题目描述 Seter建造了一个很大的星球,他准备建造N个国家和无数双向道路.N个国家很快建造好了,用1..N编号,但是他发现道路实在太多了,他要一条条建简直是不可能的!于是他以如下方式建造道路:(a,b),(c,d)表示,对于任意两个国家x,y,如果a<=x<=b,c<=y<=d,那么在xy之间建造一条道路.Seter保证不会有一个国家与自己之间有道路. Seter好不容易建好了所有道路,他现在在位于P号的首都.Seter想知道P号国家到任意一个国家最少需要经过几条道路.当然,Se

BZOJ 2763 JLOI 2011 飞行路线 分层图+最短路

题目大意:两个小屁孩要乘飞机去旅行.现在给一些无向边和边权,另外他们还有K次免费乘坐飞机的机会,问从起点到终点的最小话费是什么. 思路:分层图第一题.之前听到分层图还以为是真的建K个图,然后不同层数之间的点连边跑最短路..后来经同学讲解才发现我想多了.. 其实还是动归的思想(最短路不也是动归的思想么(`?ω?′)),f[ i ][ j ]表示在j位置时,已经用了i次免费机会的时候的最小花费,然后在SPFA里多一维的转移就可以了. PS:BZOJ上这个题还是挺卡常数的,我之前用queue用了938

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现在要从一个城市沿着航线到达另一个城市

BZOJ3627 [JLOI2014]路径规划

题意:求期望红绿灯时间下.途径若干加油站.经过最多若干个红绿灯,起点与终点的最短路. 思路:每一个有红绿灯的节点通过时间怎么算呢?其实t=red*red/2/(red+green),然后把这个时间附加到节点的出边上. 随后我们建立分层图,第i层表示经过了i个红绿灯时,从源点到该点的最短路径长度. 假设没有油量限制.那么我们直接跑最短路即可了. 注意到加油站非常少,于是我们枚举以每一个加油站为起点,向其它加油站经过若干个红绿灯的最短路径. 若此长度不大于最大油量,那么能够直接转移. 我们用上述信息

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