【破烂集】大佬的spfa

估计所有人在看过spfa之后基本都会把其他最短路的算法忘光吧,因为spfa不但超级简单,而且还超级块,所以的确非常好用,之前看到一个大佬的spfa,感觉有几个不错的优化,用了之后把我1202的一个85ms左右的算法直接优化到65ms了,还是很给力的,所以在这里贴一下,主要在于用deque代替queue,并且在push的时候通过对于这个d的大小的一个模糊的判断决定放到前面还是放到后面(queue做不到这点)。实际上可以认为deque是完爆queue的,vector是完爆stack的,因为实际上queue和stack就是用deque和vector实现的,所以从效率来说两者几乎没有区别(stack和queue应该略低),而且关键在于queue和stack屏蔽了很多容器原始的功能(因为queue本质上是为了代码更加清晰而出现的,所以并没有什么效率和功能可言)。所以这个spfa的确是更好的。顺便说一下数组模拟,stack模拟的确是不错的,但是queue模拟的话会浪费很大的空间,所以还是谨慎对待为好。另外不要迷信什么数组模拟,有道xdoj上的题数组模拟比deque慢。

发现之前学艺不精,这个大佬的模板抄错了,只是一个细微的不同,但是差别还是有的,那就是used根本不需要,之前我一直被spfa要used的惯性思维给蒙蔽了,首先说一点,经典的spfa是前出后入,这样的方法比后入后出(也就是stack)快了不知道多少(几十倍左右),但是因为你有了deque,所以我们可以把一些很短的点加入前方(就是deque里面已经有这个点了)这样其实效率会更高。

贴个不错的模板(已经修改)

int spfa(int s , int t)
{
    memset(d , 0x3f , sizeof(d));

    deque<int> que;
    que.push_front(s); 
    d[s] = 0;

    while(!que.empty())
    {
        int x = que.front();
        que.pop_front();

        int i;
        for(i = head[x] ; i ; i = edge[i].next)
        {
            int to = edge[i].to, cos = edge[i].cos;

            if(d[to] > d[x] + cos)
            {
                d[to] = d[x] + cos;

                if(!que.empty() && d[to] < d[que.front()])
                    que.push_front(to);
                else
                    que.push_back(to);
            }
        }
    }

    return d[t];
}

猜你喜欢

转载自blog.csdn.net/qq_40772738/article/details/81950743