【问题标题】:Trouble with Dijkstra , finding all minimum pathsDijkstra 的麻烦,找到所有最小路径
【发布时间】:2013-05-17 17:56:47
【问题描述】:

这里有一个问题,我们试图在图中找到从一个节点到另一个节点的所有最短路径。我们已经实现了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;
}

这是我们的代码,我们认为我们必须修改它,但我们真的不知道在哪里。

【问题讨论】:

  • 家庭作业问题? :(
  • spoj 问题,证明自己
  • 我认为 Dijkstra 只能解决单源最短路径问题,而你想对所有需要的顶点都这样做Floyd-Warshall
  • 是的,但我需要找到所有可能的最短路径,从单个源到特定节点

标签: c++ dijkstra


【解决方案1】:

目前,您只是保存/检索您碰巧找到的最短路径之一。考虑这个例子:

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

很明显,每个位置不能有一个 p[] 值,因为实际上第 4 个节点 (3) 之前有 2 个有效节点:12

因此,您可以将其替换为 vector&lt;int&gt; 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&lt; vector&lt;int&gt; &gt; paths;,然后将每个路径填充到 vector 中,然后将此向量推入您的 paths 向量向量中。请注意,路径的实际数量可能非常大,您将没有足够的内存来存储所有路径,并且每次找到新路径时,您都需要调用需要使用路径的任何函数(即,当t == -1findpath() 中时)。
猜你喜欢
  • 2011-02-18
  • 1970-01-01
  • 2016-07-13
  • 1970-01-01
  • 2016-07-30
  • 1970-01-01
  • 2021-03-07
  • 2011-05-11
相关资源
最近更新 更多