Dijkstra算法的问题,如何找到所有最短路径

3

我们遇到了一个问题,我们想要找出图中从一个节点到另一个节点的所有最短路径。我们已经实现了dijkstra算法,但是我们真的不知道如何找到它们全部。

我们需要使用BFS吗?

#include <vector>
#include <iostream>
#include <queue>
using namespace std;

typedef pair <int, int> dist_node;
typedef pair <int, int> edge;
const int MAXN = 10000;
const int INF = 1 << 30;
vector <edge> g[MAXN];
int d[MAXN];
int p[MAXN];

int dijkstra(int s, int n,int t){
    for (int i = 0; i <= n; ++i){
        d[i] = INF;  p[i] = -1;
    }
    priority_queue < dist_node, vector <dist_node>,greater<dist_node> > q;
    d[s] = 0;
    q.push(dist_node(0, s));
    while (!q.empty()){
        int dist = q.top().first;
        int cur = q.top().second;
        q.pop();
        if (dist > d[cur]) continue;
        for (int i = 0; i < g[cur].size(); ++i){
            int next = g[cur][i].first;
            int w_extra = g[cur][i].second;
            if (d[cur] + w_extra < d[next]){
                d[next] = d[cur] + w_extra;
                p[next] = cur;
                q.push(dist_node(d[next], next));
            }
        }
    }
    return d[t];
}

vector <int> findpath (int t){
    vector <int> path;
    int cur=t;
    while(cur != -1){
        path.push_back(cur);
        cur = p[cur];
    }
    reverse(path.begin(), path.end());
    return path;
}

这是我们的代码,我们相信需要修改它,但我们真的不知道在哪里。

作业问题?:( - Jimmy Lu
SPOJ问题,证明自己 - user2394968
1
我认为Dijkstra算法只能解决单源最短路径问题,如果你想对所有顶点进行计算,你需要像Floyd-Warshall算法这样的东西。Floyd-Warshall - anana
是的,但我需要找到从单个源节点到特定节点的所有可能的最短路径。 - user2394968
1个回答

1

目前,您只保存/检索可能找到的最短路径之一。考虑以下示例:

4 nodes
0 -> 1
0 -> 2
1 -> 3
2 -> 3

很明显,对于每个位置,你不能只有一个单独的p[]值,实际上第4个节点(3)有2个前面的有效节点:12
因此,你可以用vector<int> p[MAXN];替换它,并按以下方式操作:
if (d[cur] + w_extra < d[next]){
    d[next] = d[cur] + w_extra;
    p[next].clear();
    p[next].push_back(cur);
    q.push(dist_node(d[next], next));
}
else if(d[cur] + w_extra == d[next]){
    p[next].push_back(cur); // a new shortest way of hitting this same node
}

你还需要更新findpath()函数,因为它需要处理导致多个路径的“分支”,这可能会产生指数级别的巨大路径数量,具体取决于图形。如果你只需要打印路径,可以像这样做:
int answer[MAXN];

void findpath (int t, int depth){
    if(t == -1){ // we reached the initial node of one shortest path
        for(int i = depth-1; i >= 0; --i){
            printf("%d ", answer[i]);
        }
        printf("%d\n", last_node); // the target end node of the search
        return;
    }
    for(int i = p[t].size()-1; i >= 0; --i){
        answer[depth] = p[t][i];
        findpath(p[t][i], depth+1);
    }
}

请注意,在开始使用Dijkstra算法之前,您需要执行p[s].push_back(-1)操作,并在每个测试用例之间清除该向量数组。

你可以在那个时候将它们保存下来,而不是打印出来。你需要一个全局结构,比如 vector< vector<int> > paths;,并将每个路径填充到一个 vector<int> 中,然后将这个向量推入你的 paths 向量中。请注意,实际路径的数量可能非常大,您可能没有足够的内存来存储所有路径,因此您需要在找到新路径时(即在 findpath()t == -1 时)每次调用需要使用路径的任何函数。 - i Code 4 Food

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接