估计所有人在看过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];
}