题目大意:给定一个无向图,每条边有边权,有些点有点权,一些点是加油站,求一条起点到终点的最短路,使经过有点权的点不超过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;
}
}