「BZOJ2100」[USACO10DEC] 苹果交货Apple Delivery - SPFA+SLF
[USACO10DEC]苹果交货Apple Delivery
时空限制 1000ms / 128MB
现在,贝西要从牧场\(PB\)开始给\(PA_1\)和\(PA_2\)牧场各送一个苹果(\(PA_1\)和\(PA_2\)顺序可以调换),那么最短的距离是多少呢?当然,\(PB\)、\(PA_1\)和\(PA_2\)各不相同。
输入格式:
Line \(1\): Line \(1\) contains five space-separated integers: \(C, P, PB, PA1\), and \(PA2\)
Lines \(2\)..\(C+1\): Line \(i+1\) describes cowpath \(i\) by naming two pastures it connects and the distance between them: \(P1_i\), \(P2_i\), \(D_i\)
输出格式:
Line \(1\): The shortest distance Bessie must travel to deliver both apples
思路
直接SPFA的话会T两个点(显然),所以我们要用一种玄学优化:SLF (LLL被卡爆了而且不稳定不要用)
SLF:Small Label First 策略,利用deque,设要加入的节点是j,队首元素为i,若dist(j) < dist(i),则将j插入队首,否则插入队尾。
这个东西大概可以让你的SPFA快上\(20\)%左右,上代码
代码
#include<cstdio>
#include<cstring>
#include<cctype>
#include<algorithm>
#include<iostream>
#include<queue>
#define rg register
using namespace std;
inline int read(){
rg int f=0,x=0;
rg char ch=getchar();
while(!isdigit(ch)) f|=(ch=='-'),ch=getchar();
while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
return f?-x:x;
}
const int N =25010;
const int M =150010;
const int inf =0x7f7f7f7f;
int n,r,p,s,head[N],tot,dis[N];
bool vis[N];
struct edge{
int to,nxt,w;
}e[M];
inline void add(rg int u,rg int v,rg int w){
e[++tot].to=v;
e[tot].w=w;
e[tot].nxt=head[u];
head[u]=tot;
}
inline void spfa(rg int s){
for(rg int i=1;i<=n;++i) dis[i]=inf;
dis[s]=0;
deque<int > q;
q.push_back(s);
while(!q.empty()){
int u=q.front();
q.pop_front();
vis[u]=false;
for(rg int i=head[u];i;i=e[i].nxt){
int v=e[i].to;
if(dis[v]>dis[u]+e[i].w){
dis[v]=dis[u]+e[i].w;
if(!vis[v]){
vis[v]=true;
if(q.empty()||dis[v]>dis[q.front()]) q.push_back(v);
else q.push_front(v);
}
}
}
}
}
signed main(){
n=read(),r=read(),p=read(),s=read();
for(rg int i=1;i<=r;++i){
int u=read(),v=read(),w=read();
add(u,v,w),add(v,u,w);
}
for(rg int i=1;i<=p;++i){
int u=read(),v=read(),w=read();
add(u,v,w);
}
spfa(s);
for(rg int i=1;i<=n;++i)
if(dis[i]==inf) printf("NO PATH\n");
else printf("%d\n",dis[i]);
return 0;
}