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

猜你喜欢

转载自www.cnblogs.com/horrigue/p/9642919.html