SPFA最短路径算法详解

算法思路

用一个队列储存当前可能用于更新邻接
点的点,每次取出队首更新邻接点,若邻接点能被
更新,则把该点塞进队列(保证队列中没有相同的
点)。
看起来是个很不靠谱的算法,SPFA 只能在随机数据
下或者在某些 DP 模型中运行良好。
下面我们通过『怎样卡SPFA』来理解这个算法的问
题到底在哪

知识点 – 怎样卡 SPFA

第一种卡法其实和卡写错的 Dijkstra 的方法一样:
SPFA 虽然保证点不会重复,但不能保证一个点不会多次入队。

第二种是网格图。
SPFA 并没有规定点入队出队的顺序,它更像是 BFS。
我们只需要骗 SPFA 作很多次无效的更新即可(也就
是更新很多次但是没有得到最终答案)。

 代码实现:

void spfa(const int &st_point) 
{
	memset(dst, 0x3f, sizeof dst);
	std::queue<int> que;
	dst[st_point] = 0;
	que.push(st_point), isfix[st_point] = true;
	while (!que.empty()) 
	{
		int u = que.front();
		que.pop(), isfix[u] = false;
		for (int it = grp[u]; it; it = grp.nxt[it]) 
		{
			int v = grp.lnk[it];
			if (dst[v] > dst[u] + grp.wgt[it])
			{
				dst[v] = dst[u] + grp.wgt[it];
				if (!isfix[v]) isfix[v] = true, que.push(v);
			}
		}  
	} 
}

问题 K: 【一本通图 最短路径算法】最短路(Spfa)

[题目描述]

#include <stdio.h>
#include <string.h>
#define INF 999999999;
struct node
{
    int to, next, w;
}e[1001000];
int q[1000100], h, t, cnt = 0, head[100100], vis[100010], d[100010];
void add(int u, int v, int w)
{
    cnt++;
    e[cnt].to = v;
    e[cnt].w = w;
    e[cnt].next = head[u];
    head[u] = cnt;
    cnt++;
    e[cnt].to = u;
    e[cnt].w = w;
    e[cnt].next = head[v];
    head[v] = cnt;
}
int main()
{
    int n, m, i, j, u, v, w, b;
    memset(head, 0, sizeof(head));
    memset(vis, 0, sizeof(vis));
    scanf("%d%d", &n, &m);
    for(i = 1; i <= m; i++)
    {
        scanf("%d%d%d", &u, &v, &w);
        add(u, v, w);
    }
    for(i = 1; i <= n; i++)
        d[i] = INF;
    d[1] = 0;
    h = t = 1;
    q[t] = 1;
    vis[1] = 1;
    t++;
    while(h < t)
    {
        u = q[h];
        b = head[u];
        while(b != 0)
        {
            v = e[b].to;
            if(d[v] > d[u] + e[b].w)
            {
                d[v] = d[u] + e[b].w;
                if(vis[v] == 0)
                {
                    vis[v] = 1;
                    q[t] = v;
                    t++;
                }
            }
            b = e[b].next;
        }
        vis[u] = 0;
        h++;
    }
    printf("%d\n", d[n]);
    return 0;
}

posted @ 2022-07-27 11:47  不怕困难的博客  阅读(40)  评论(0编辑  收藏  举报  来源