title

「BZOJ2100」[USACO10DEC] 苹果交货Apple Delivery - SPFA+SLF

->点我进原题

[USACO10DEC]苹果交货Apple Delivery


时空限制 1000ms / 128MB


贝西有两个又香又脆的红苹果要送给她的两个朋友。当然她可以走的$C$($1<=C<=200000$)条“牛路”都被包含在一种常用的图中,包含了P($1<=P<=100000$)个牧场,分别被标为$1$..$P$。没有“牛路”会从一个牧场又走回它自己。“牛路”是双向的,每条牛路都会被标上一个距离。最重要的是,每个牧场都可以通向另一个牧场。每条牛路都连接着两个不同的牧场$P1_i$和$P2_i$($1<=P1_i,p2_i<=P$),距离为$D_i$。所有“牛路”的距离之和不大于$2000000000$。

现在,贝西要从牧场\(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;
}
posted @ 2018-09-13 20:26  Horrigue_JyowYang  阅读(189)  评论(0编辑  收藏  举报