zoukankan      html  css  js  c++  java
  • 关于SPFA算法的优化方式

    关于SPFA算法的优化方式

    这篇随笔讲解信息学奥林匹克竞赛中图论部分的求最短路算法SPFA的两种优化方式。学习这两种优化算法需要有SPFA朴素算法的学习经验。在本随笔中SPFA朴素算法的相关知识将不予赘述。

    上课!

    No.1 SLF优化(Small Label First)

    顾名思义,这种优化采用的方式是把较小元素提前。

    就像dijkstra算法的堆优化一样。我们在求解最短路算法的时候是采取对图的遍历,每次求最小边的一个过程,为了寻找最小边,我们需要枚举每一条出边,如果我们一上来就找到这个边,那当然是非常爽的。一次找一次爽,一直找一直爽。所以我们采用了这种优化方式。

    具体实现方式是把原来的队列变成双端队列,如果新入队的元素比队首元素还要小,就加入到队首,否则排到队尾。

    模板如下:

    void spfa()
    {
    	memset(dist,0x3f,sizeof(dist));
    	memset(v,0,sizeof(v));
        deque<int> q;
        q.push_back(1);
        v[1]=1;
        dist[1]=0;
        while(!q.empty())
        {
            int x=q.front();
            q.pop_front();
            v[x]=0;
            for(int i=head[x];i;i=nxt[i])
            {
                int y=to[i];
                if(dist[y]>dist[x]+val[i])
                {
                    dist[y]>dist[x]+val[i];
                    if(v[y]==0)
                   	{
                        if(dist[y]<=dist[q.pront()])
                            q.push_front(y);
                       	else
                            q.push_back(y);
                        v[y]=1;
    				}
                }
    		}
    	}
    }
    

    No.2 LLL优化(Large Label Last)

    顾名思义,它的策略是把大的元素放到后面。

    你会说,这不跟上面的一样么?

    不不不,这个优化针对的是出队元素。它的实现过程是:对于每个出队元素,比较它的dist[]和队列中dist的平均值,如果它的dist[]更大,将它弹出放到队尾。以此类推,直至dist[x]小于其平均值。

    模板:

    void spfa()
    {
        memset(dis, 0x3f, sizeof(dis));
        queue<int> q;
        q.push(1);
        v[1] = 1;
        dist[1] = 0;
        cnt = 1;
        while(!Q.empty()) 
        {
            int x = q.front();
            while (dis[x]*cnt > sum) 
            {
                q.pop();
                q.push(x);
                x = q.front();
            }
            q.pop();
            cnt--;
            sum -= dist[x];
            v[x] = 0;
            for (int i = head[x]; i ; i=nxt[i]) 
            {
                int y=to[i];
                if (dist[y] > dist[x] + val[i]) 
                {
                    dist[y] = dist[x] + val[i];
                    if (v[y]==0) 
                    {
                        q.push(y);
                        sum += dist[y];
                        cnt++;
                    }
                }
            }
        }
    }
    

    重点来了!!

    No.3 SLF+LLL同时优化!

    听名字就很高级。

    是的,的确很高级,不仅高级,而且快。

    我就直接上模板了。

    void spfa()
    {
        memset(dist, 0x3f, sizeof(dist));
        memset(v,0,sizeof(v));
        deque<int> q;
        q.push_back(1);
        v[1] = 1;
        dist[1] = 0;
        cnt = 1;
        while (!q.empty()) 
        {
            int x = q.front();
            while (cnt*dist[x] > sum) 
            {
                q.pop_back();
                q.push_back(x);
                x = q.front();
            }
            q.pop_front();
            cnt--;
            sum -= dist[x];
            v[x] = 0;
            for (int i = head[x]; i ; i=nxt[i]) 
            {
                int y=to[i];
                if (dist[y] > dist[x] + val[i]) 
                {
                    dist[y] = dist[x] + val[i];
                    if (!v[y]) 
                    {
                        if (dist[y] <= dist[q.front()])
                            q.push_front(y);
                        else 
                            q.push_back(y);
                        v[y] = 1;
                        sum += dist[y];
                        cnt++;
                    }
                }
            }
        }
    }
    

    下课!祝同学们AK IOI!!

  • 相关阅读:
    P1012 拼数(水题)
    oracle 存储过程中调用同义词报错“表和视图不存在”
    C#文件相对路径
    C# WebAPi接收和发送图片
    EFCore学习笔记一:(安装EFCore并根据Code First生成数据库)
    Winform切换登录用户
    Winform中子控件Dock排列顺序问题
    ORA-28001: the password has expired解决方法
    C#实体类生成XML(注意<![CDATA]>标签的不解析)
    一次完整的HTTP请求过程
  • 原文地址:https://www.cnblogs.com/fusiwei/p/11289019.html
Copyright © 2011-2022 走看看