关于SPFA的优化

来源:互联网 发布:数据圈论坛怎么打开 编辑:程序博客网 时间:2024/06/07 20:02

SPFA算法有两种优化算法 SLF 和 LLL
SLF:Small Label First 大概是双向队列?
如果要加入的元素v的距离dis[v]比当前的队首元素dis[q[head]]小的话,那么就把当前元素插到队首。
如果是手打队列的话,就先head-2,再q[head+1]=v;
LLL:Large Label Last
如果队列q的队首元素为x,队列中所有元素的平均距离为dist,如果dis[x]>dist,则将它移动到末尾,如果有一个元素的dis[x]<=dist,则将它出队。

贴个板:
(两个优化都有加)
(以bzoj 4152 为例 题面就不贴了)
但这道题跟SPFA有仇,SPFA应该是过不了的,要用dijkstra+堆优化

//这道题是有多看不起SPFA //SLF && LLL//然而有什么用呢 还是T掉了 #include<cstdio>#include<cstring>#include<algorithm>#define ms(x,y) memset(x,y,sizeof(x))#include<queue>#define ll long longusing namespace std;const int N = 200000 + 10;const int M = N*4;inline ll read(){    ll data=0,w=1; char ch=0;    while(ch!='-' && (ch<'0' || ch>'9')) ch=getchar();    if(ch=='-') w=-1,ch=getchar();    while(ch>='0' && ch<='9') data=data*10+ch-'0',ch=getchar();    return data*w;}int n;deque<int> q;struct Node{    ll x,y;    int i;}a[N];struct node{    int pre,v;    ll w;}edge[M];int num=0;int head[N];void addedge(int from,int to,ll w){    num++;    edge[num].pre=head[from];    edge[num].v=to;    edge[num].w=w;    head[from]=num;}bool cmp1(const Node &a,const Node &b){    return a.x<b.x;}bool cmp2(const Node &a,const Node &b){    return a.y<b.y;}void getmap(){    sort(a+1,a+n+1,cmp1);    for(register int i=2;i<=n;i++){        ll w=a[i].x-a[i-1].x;        addedge(a[i-1].i,a[i].i,w);        addedge(a[i].i,a[i-1].i,w);    }    sort(a+1,a+n+1,cmp2);    for(register int i=2;i<=n;i++){        ll w=a[i].y-a[i-1].y;        addedge(a[i-1].i,a[i].i,w);        addedge(a[i].i,a[i-1].i,w);    }   }ll dis[N];bool exist[N];int tot;ll sum=0;void SPFA(){    ms(dis,127);ms(exist,0);    q.push_back(1),dis[1]=0,exist[1]=true,tot=1;    while(!q.empty()){        int u=q.front();q.pop_front();        if(dis[u]*tot>sum){            q.push_back(u);            continue;        }        exist[u]=false;tot--,sum -= dis[u];        for(int i=head[u];i;i=edge[i].pre){            int v=edge[i].v;            if(dis[v]>dis[u]+edge[i].w){                dis[v]=dis[u]+edge[i].w;                if(!exist[v]){                    exist[v]=true;                    if(!q.empty()&&dis[v]<dis[q.front()]) q.push_front( v ) ;                    else q.push_back(v);                    tot++,sum+=dis[v];                }            }        }    }}int main(){    scanf("%d",&n);    for(register int i=1;i<=n;i++){        a[i].x=read(),a[i].y=read();        a[i].i=i;    }    getmap();/*  for(int i=head[1];i;i=edge[i].pre){        int v=edge[i].v;        printf("%d %d\n",v,edge[i].w);    }*/    SPFA();    printf("%lld",dis[n]);    return 0;}