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;
	}
}


你可能感兴趣的:(堆,SPFA,bzoj,BZOJ3627,分层图)