洛谷P3003 [USACO10DEC]苹果交货Apple Delivery

来源:互联网 发布:手机屏幕镜像软件 编辑:程序博客网 时间:2024/06/08 08:03

首先,这题思路很清晰,因为只有两条路,s->1->2或s->2->1,因此分别用1和2做两遍SPFA,取较小的一个就好了。
这题值得注意的是时间,很多人是70分,你一定是用的裸的SPFA,因为我就是这么干的,然后3个TLE,怎么办呢?这时就要用到SPFA的优化了,哔(不要问我为什么),有请SLF出场!
SLF(Small Label First),意思就是小的在前,具体就是:假设要进队的点是t,队首元素是f,那么如果d[t]< d[f],就把t放队首,否则放队尾。
此时肯定有人问,怎么放队首呢?办法还是出自c++的STl,c++强大的STl中有一个双端队列deque,头尾都可以加元素,这样问题就解决了。它的原理应该和dijkstra是一(bu)样(tong)的。
貌似还有一个优化更好,叫LLL,Large Label Last,可以自行百度,我不多做介绍。
SLF可以优化15%~20%,LLL可以优化50%,自己看情况使用(不过此题SLF就过了)。
下来贴代码:

#include<bits/stdc++.h>#define inf 2100000000using namespace std;struct edge{    int to,next,w;}e[400001];int m,n,s,a,b,tot=0;int d[100001];int head[100001];int in[100001];void addedge(int x,int y,int l){    tot++;    e[tot].to=y;    e[tot].w=l;    e[tot].next=head[x];    head[x]=tot;}deque<int> q;void spfa(int st){    memset(in,0,sizeof(in));    memset(d,127,sizeof(d));    d[st]=0;    in[st]=1;    q.push_front(st);    while(!q.empty()){        int k=q.front();        q.pop_front();        in[k]=0;        for(int i=head[k];i!=0;i=e[i].next){            if(d[k]+e[i].w<d[e[i].to]){                d[e[i].to]=d[k]+e[i].w;                if(!in[e[i].to]){                    if(!q.empty()&&d[e[i].to]<d[q.front()]){                        q.push_front(e[i].to);                    }                    else{                        q.push_back(e[i].to);                    }                }            }        }    }}int main(){    cin>>m>>n>>s>>a>>b;    for(int i=1;i<=m;i++){        int x,y,l;        scanf("%d %d %d",&x,&y,&l);        addedge(x,y,l);        addedge(y,x,l);    }    int ans1=0;    int ans2=0;    spfa(a);    ans1+=d[b]+d[s];    spfa(b);    ans2+=d[a]+d[s];    int ans=min(ans1,ans2);    cout<<ans;    return 0;}
阅读全文
0 0