zoukankan      html  css  js  c++  java
  • spfa及其优化

    发现spfa居然也有优化,十分的震惊,现在由我细细道来(#^.^#)

    Description
        给你一个有向且边权全部非负的图,输出1到n的最短路。
    Input
        第一行两个自然数n(n<=100000)和m(m<=200000),表示点数和边数。接下来m行,每行3个数a,b,l,其中1<=a,b<=n,l<=1000。
    Output
        仅一个整数,为1到n的最短路。如果无解,输出-1。
    Sample Input
    10 10
    1 5 46
    1 10 50
    2 7 23
    3 4 40
    3 7 3
    3 9 21
    4 9 27
    5 8 45
    5 10 30
    7 10 15
    Sample Output
    50
    Hint
     如果是练SPFA,过90分就可以了(不过如果你的SPFA可以过完,在下拜你为师……)。

    这个出题人要拜我为师o(* ̄︶ ̄*)o

    我们会想一下bell——ford如何进化到spfa.

    SPFA对Bellman-Ford算法优化的关键之处在于意识到:只有那些在前一遍松弛中改变了距离估计值的点,才可能引起他们的邻接点的距离估计值的改变。因此,算法大致流程是用一个队列来进行维护,即用一个先进先出的队列来存放被成功松弛的顶点。初始时,源点s入队。当队列不为空时,取出队首顶点, 对它的邻接点进行松弛。如果某个邻接点松弛成功,且该邻接点不在队列中,则将其入队。经过有限次的松弛操作后,队列将为空,算法结束。SPFA算法的实现,需要用到一个先进先出的队列queue 和一个指示顶点是否在队列中的标记数组mark。为了方便查找某个顶点的邻接点,图采用邻接表存储。

    这样,我们的加入队列的顺序是随机的,现在,让我们看看两个优化。

    一个叫做SLF,一个叫做LLL,先%一下

    SLF又称Small Label First 策略. (比较常用)

    比较当前点和队首元素,如果小于队首,则插入队首,否则加入队尾

    这个优化有什么道理呢,我想是这样的

    1.每次加入了边后,都要对可以到达的点松弛,如果先加入队列的元素足够小,那么他的更新效果更加彻底,下一次碰到与这个点相连的点,这个点就很大概率不会入队了,这样就可以减少运算了

    嘿嘿(#^.^#)

    而LLL又称LLL: Large Label Last 策略. (不太常用)

    设队首元素为i,每次弹出时进行判断,队列中所有dist值的平均值为x,若dist(i)>x则将i插入到队尾,查找下一元素,直到找到某一i使得dist(i)<=x,则将i出对进行松弛操作。

    据说一些数据卡LLL可以卡到指数级只不过LLL还是挺好的(以后还是LLL少用)

    发一个SLF优化的代码

    #include<bits/stdc++.h>
    
    using namespace  std;
    
    const int maxn=100000+10;
    
    const int INF=0x7FFFFFFF;
    
    int pre[maxn];
    
    int dis[maxn];
    
    int path[maxn];
    
    bool vis[maxn];
    
    int head[maxn];
    int n,m;
    
    int tot,cnt;
    struct node
    {
        int v,w,next;
    }E[2*maxn];
    void add(int u,int v,int w)
    {
    
        E[tot].v=v;
    
        E[tot].w=w;
    
        E[tot].next=head[u];
    
        head[u]=tot++;
    
    }
     void init()
    
    {
    
        tot=0;
    
        memset(vis,false,sizeof((vis)));
    
        memset(head,-1,sizeof(head));
    
    }
    
    void spfa(int st)
    
    {
    
        for(int i=1;i<=n;i++)
            vis[i]=false,dis[i]=INF;
        int now,next;
        dis[st]=0;
        vis[st]=true;
        deque<int>q;
        q.push_back(st);
        pre[st]=-1;
        while(!q.empty())
        {
            now=q.front();
            q.pop_front();
            vis[now]=false;
            for(int i=head[now];i!=-1;i=E[i].next)
            {
                next=E[i].v;
                if(dis[next]>dis[now]+E[i].w)
                {
                    dis[next]=dis[now]+E[i].w;
                    pre[next]=now;
                     if(!vis[next])
                     {
                          vis[next]=true ; 
                         if( q.empty()||dis[next]>dis[q.front()]) q.push_back(next);
                             else q.push_front(next);
                    }
                }
    
            }
    
        }
    
    }
    void print(int x)
    {
        if(pre[x]==-1) return;
        print(pre[x]);
        printf("%d ",x);
    }
    int main()
    
    {
            init();
            scanf("%d%d",&n,&m);
                  // int st,en;
    //        scanf("%d%d",&st,&en);
            int u,v,w;
            for(int i=1;i<=m;i++){scanf("%d%d%d",&u,&v,&w);add(u,v,w);}
            spfa(1);
            if(dis[n]==INF)
            {printf("-1");return 0;}
            printf("%d
    ",dis[n]);
            //printf("%d ",st);
            //print(en);
    
            printf("
    ");
    
        
        return 0;
    }

     不知道为什么加了两个优化以后又T了,莫名其妙(我以后不用LLL了)╭(╯^╰)╮;

    #include<bits/stdc++.h>
    
    using namespace  std;
    
    const int maxn=100000+10;
    
    const int INF=0x7FFFFFFF;
    
    int pre[maxn];
    
    int dis[maxn];
    
    int path[maxn];
    
    bool vis[maxn];
    
    int head[maxn];
    int n,m;
    
    int tot,cnt;
    struct node
    {
        int v,w,next;
    }E[2*maxn];
    void add(int u,int v,int w)
    {
    
        E[tot].v=v;
    
        E[tot].w=w;
    
        E[tot].next=head[u];
    
        head[u]=tot++;
    
    }
     void init()
    
    {
    
        tot=0;
    
        memset(vis,false,sizeof((vis)));
    
        memset(head,-1,sizeof(head));
    
    }
    
    void spfa(int st)
    
    {
    
        for(int i=1;i<=n;i++)
            vis[i]=false,dis[i]=INF;
        int now,next;
        dis[st]=0;
        vis[st]=true;
        deque<int>q;
        q.push_back(st);
        pre[st]=-1;int tot=1;
        int sum=0;
        while(!q.empty())
        {
            now=q.front();
            q.pop_front();
            vis[now]=false;
            tot--; sum-=dis[now] ;
            for(int i = head[now];i != -1;i = E[i].next)
            {
                next = E[i].v;
                if(dis[next]>dis[now]+E[i].w)
                {
                    dis[next]=dis[now]+E[i].w;
                    pre[next]=now;
                     if(!vis[next])
                     {
                          vis[next]=true ; 
                         if( q.empty()||dis[next]>dis[q.front()]||dis[next] * tot <= sum) q.push_back(next);
                             else q.push_front(next);
                         tot++;sum+=dis[next];    
                    }
                }
    
            }
    
        }
    
    }
    void print(int x)
    {
        if(pre[x]==-1) return;
        print(pre[x]);
        printf("%d ",x);
    }
    int main()
    
    {
            init();
            scanf("%d%d",&n,&m);
                  // int st,en;
    //        scanf("%d%d",&st,&en);
            int u,v,w;
            for(int i=1;i<=m;i++){scanf("%d%d%d",&u,&v,&w);add(u,v,w);}
            spfa(1);
            if(dis[n]==INF)
            {printf("-1");return 0;}
            printf("%d
    ",dis[n]);
            //printf("%d ",st);
            //print(en);
    
            printf("
    ");
    
        
        return 0;
    }
  • 相关阅读:
    hdu 5119 Happy Matt Friends
    hdu 5128 The E-pang Palace
    hdu 5131 Song Jiang's rank list
    hdu 5135 Little Zu Chongzhi's Triangles
    hdu 5137 How Many Maos Does the Guanxi Worth
    hdu 5122 K.Bro Sorting
    Human Gene Functions
    Palindrome(最长公共子序列)
    A Simple problem
    Alignment ( 最长上升(下降)子序列 )
  • 原文地址:https://www.cnblogs.com/star-eternal/p/7602474.html
Copyright © 2011-2022 走看看