SPFA算法模板

    大概思路是用一个队列来进行维护, 初始时将源加入队列。 每次从队列中取出一个元素,并对所有与他相邻的点进行松弛,若某个相邻的点松弛成功,则将其入队。 直到队列为空时算法结束。它可以在O(kE)的时间复杂度内求出源点到其他所有点的最短路径,可以处理负边。

   自己不太理解,以后再说吧。

   附上实例+模板一个。

#include <iostream>

#include <cstdio>

using namespace std;

/*==================================================*\

 |  SPFA(Shortest Path Faster Algorithm)

Bellman-Ford算法的一种队列实现,减少了不必要的冗余计算。 它可以在

O(kE)的时间复杂度内求出源点到其他所有点的最短路径,可以处理负边。

原理:只有那些在前一遍松弛中改变了距离估计值的点,才可能引起他们的邻

接点的距离估计值的改变。

判断负权回路:记录每个结点进队次数,超过|V| 次表示有负权。

\*==================================================*/

// POJ 3159 Candies

const int INF = 0x3F3F3F3F;

const int V = 30001;

const int E = 150001;

int pnt[E], cost[E], nxt[E];

int e, head[V];

int dist[V];

bool vis[V];

inline void addedge(int u, int v, int c)

{

    pnt[e] = v;

    cost[e] = c;

    nxt[e] = head[u];

    head[u] = e++;

}

int relax(int u, int v, int c)

{

    if( dist[v] > dist[u] + c )

    {

        dist[v] = dist[u] + c;

        return 1;

    }

    return 0;

}



int SPFA(int src, int n)

{

    // 此处用堆栈实现,有些时候比队列要快

    int  i;

    for( i=1; i <= n; ++i )  // 顶点1...n

    {

        vis[i] = 0;

        dist[i] = INF;

    }

    dist[src] = 0;

    int  Q[E], top = 1;

    Q[0] = src;

    vis[src] = true;

    while( top )

    {

        int  u, v;

        u = Q[--top];

        vis[u] = false;

        for( i=head[u]; i != -1; i=nxt[i] )

        {

            v = pnt[i];

            if( 1 == relax(u, v, cost[i]) && !vis[v] )

            {

                Q[top++] = v;

                vis[v] = true;

            }

        }

    }

    return dist[n];

}

int main(void)

{

    int  n, m;

    while( scanf("%d%d", &n, &m) != EOF )

    {

        int  i, a, b, c;

        e = 0;

        memset(head, -1, sizeof(head));

        for( i=0; i < m; ++i )

        {

            // b-a <= c, 有向边(a, b):c ,边的方向!!!

            scanf("%d%d%d", &a, &b, &c);

            addedge(a, b, c);

        }

        printf("%d\n", SPFA(1, n));

    }

    return 0;

}

 

你可能感兴趣的:(SPFA)