Graph 最短路径更快-SPFA算法?

Graph 最短路径更快-SPFA算法?,graph,shortest-path,Graph,Shortest Path,我正在实现一个k-最短顶点不相交路径算法,需要一个 寻找最短路径的快速算法。有负权重,所以我不能 使用dijkstra和bellman ford是O(东北)。在我最近读到的一篇论文中,作者 使用所谓的SPFA算法在具有 负权重,根据他们的说法,它的复杂性为O(e)。声音 很有趣,但我似乎找不到关于算法的信息。表面上 这是原作吗 文件,但我没有权限 有没有人有好的信息或者这个算法的实现? 还有,有没有关于k-最短顶点不相交路径问题的来源? 我什么也找不到 谢谢 SPFA算法是对Bellman Fo

我正在实现一个k-最短顶点不相交路径算法,需要一个 寻找最短路径的快速算法。有负权重,所以我不能 使用dijkstra和bellman ford是O(东北)。在我最近读到的一篇论文中,作者 使用所谓的SPFA算法在具有 负权重,根据他们的说法,它的复杂性为O(e)。声音 很有趣,但我似乎找不到关于算法的信息。表面上 这是原作吗 文件,但我没有权限

有没有人有好的信息或者这个算法的实现? 还有,有没有关于k-最短顶点不相交路径问题的来源? 我什么也找不到


谢谢

SPFA算法是对Bellman Ford的优化。而在贝尔曼福特,我们只是盲目地通过每个边进行V轮,而在SPFA中,保持一个队列以确保我们只检查那些松弛的顶点。这个想法与迪杰斯特拉的类似。它也具有与BFS相同的风格,但一个节点可以多次放入队列

首先将源添加到队列中。然后,当队列不为空时,从队列中弹出一个顶点u,我们查看它的所有邻居v。如果v的距离改变,我们将v添加到队列中(除非它已经在队列中)

作者证明了SPFA通常是快的(\Theta(k | E |),其中k<2)

这里是来自的伪代码,您还可以在其中找到C语言的实现

Procedure SPFA;
Begin
  initialize-single-source(G,s);
  initialize-queue(Q);
  enqueue(Q,s);
  while not empty(Q) do 
    begin
      u:=dequeue(Q);
      for each v∈adj[u] do 
        begin
          tmp:=d[v];
          relax(u,v);
          if (tmp<>d[v]) and (not v in Q) then
            enqueue(Q,v);
        end;
    end;
End;
程序SPFA;
开始
初始化单个源(G,s);
初始化队列(Q);
排队(Q,s);
而不是空(Q)做什么
开始
u:=出列(Q);
每v∈做某事
开始
tmp:=d[v];
放松(u,v);
如果(tmpd[v])和(不是Q中的v),则
排队(Q,v);
结束;
结束;
结束;

寻找最短路径实际上是一个很好的算法。它也被认为是由队列重写的Bellmen-Ford算法。但在我看来,它喜欢BFS。它的复杂性是O(ke)(e表示边数,k)≈ 2) .虽然我一点也不懂,但在大多数问题上它都很快,特别是当只有几条边的时候

Func spfa(start, to) {
  dis[] = {INF}
  visited[] = false 
  dis[start] = 0
  // shortest distance
  visited[start] = true 
  queue.push(start)
  // push start point
  while queue is not empty {
    point = queue.front()
    queue.pop()
    visited[point] = false
    // marked as unvisited                    
    for each V from point {
      dis[V] = min(dis[V],dis[point] + length[point, V]);
      if visited[V] == false {
        queue.push(V)
        visited[V] = true
      }
    }
  }
  return dis[to]
}
它也很容易获得路径&更多 希望我能帮助你(●—●) 来自OIer的贝尔曼·福特

SPFA和贝尔曼福特基本上是一样的,所以它具有相同的最坏情况复杂性

SPFA是对贝尔曼福特的优化

C++中的SPFA,用于PS:

using namespace std;

const int INF = INT_MAX / 4;
struct node { int v, w; };
vector<int> SPFA(int max_v, int start_v, vector<vector<node>>&adj_list) {
    vector<int> min_dist(max_v + 1, INF);
    min_dist[start_v] = 0;
    queue<node> q; q.push({ start_v,0 });
    queue<int> qn; qn.push(0);
    while (q.size()) {
        node n = q.front(); q.pop();
        int nn = qn.front(); qn.pop();
        if (nn >= max_v) { printf("-1\n"); exit(0); }//negative cycle

        if (min_dist[n.v] < n.w) continue;
        min_dist[n.v] = n.w;

        for (node adj : adj_list[n.v]) {
            if (min_dist[adj.v] <= adj.w + n.w) continue;
            min_dist[adj.v] = adj.w + n.w;
            q.push({ adj.v, adj.w + n.w }), qn.push(nn + 1);
        }
    }
    return min_dist;
}

int main()
{
    // N: vertex cnt, M: edge cnt
    int N, M; scanf("%d%d", &N, &M);
    vector<vector<node>> adj_list(N + 1);
    for (int i = 0; i < M; i++) {
        int u, v, w; scanf("%d%d%d", &u, &v, &w);  // edge u->v, w:weigt
        adj_list[u].push_back({ v,w });
        //adj_list[v].push_back({ u,w }); in case of undirected graph
    }

    // shortest path from '1' to 'N'
    vector<int> dist = SPFA(N, 1, adj_list);
    printf("%d\n", dist[N]);
    return 0;
}
使用名称空间std;
常量int INF=int_MAX/4;
结构节点{intv,w;};
向量SPFA(整数最大值、整数起始值、向量和调整列表){
向量最小距离(最大v+1,INF);
最小距离[起始距离]=0;
队列q;q.push({start_v,0});
队列qn;qn.push(0);
while(q.size()){
节点n=q.front();q.pop();
int nn=qn.front();qn.pop();
如果(nn>=max_v){printf(“-1\n”);退出(0);}//负循环
如果(最小距离[n.v]