正如标题所述,我正在寻找的是打印受重量限制的“所有最短路径”。
示例:
我们有一个图,其边线从0-> 1-> 3的权重为6,但是我们也有路径0-> 3的权重也为6,以下算法仅返回第一个路径,我想知道是否可以同时返回两个或所有路径。还有一种更有效/更优雅的方式来打印最短路径。我仅以此代码为例,我的代码与之非常相似,但仅从源到最后一个顶点打印。
这里回答了类似的问题,但是由于我熟悉c ++,所以我无法理解代码。
#include <iostream>
#include <vector>
#include <iomanip>
#include <climits>
using namespace std;
// Data structure to store graph edges
struct Edge
{
int source, dest, weight;
};
// Recurive Function to print path of given vertex v from source vertex
void printPath(vector<int> const &parent, int v)
{
if (v < 0)
return;
printPath(parent, parent[v]);
cout << v << " ";
}
// Function to run Bellman Ford Algorithm from given source
void BellmanFord(vector<Edge> const &edges, int source, int N)
{
// count number of edges present in the graph
int E = edges.size();
// distance[] and parent[] stores shortest-path (least cost/path)
// information. Initially all vertices except source vertex have
// a weight of infinity and a no parent
vector<int> distance (N, INT_MAX);
distance[source] = 0;
vector<int> parent (N, -1);
int u, v, w, k = N;
// Relaxation step (run V-1 times)
while (--k)
{
for (int j = 0; j < E; j++)
{
// edge from u to v having weight w
u = edges[j].source, v = edges[j].dest;
w = edges[j].weight;
// if the distance to the destination v can be
// shortened by taking the edge u-> v
if (distance[u] != INT_MAX && distance[u] + w < distance[v])
{
// update distance to the new lower value
distance[v] = distance[u] + w;
// set v's parent as u
parent[v] = u;
}
}
}
// Run Relaxation step once more for Nth time to
// check for negative-weight cycles
for (int i = 0; i < E; i++)
{
// edge from u to v having weight w
u = edges[i].source, v = edges[i].dest;
w = edges[i].weight;
// if the distance to the destination u can be
// shortened by taking the edge u-> v
if (distance[u] != INT_MAX && distance[u] + w < distance[v])
{
cout << "Negative Weight Cycle Found!!";
return;
}
}
for (int i = 0; i < N; i++)
{
cout << "Distance of vertex " << i << " from the source is "
<< setw(2) << distance[i] << ". It's path is [ ";
printPath(parent, i); cout << "]" << '\n';
}
}
// main function
int main()
{
// vector of graph edges as per above diagram
vector<Edge> edges =
{
// (x, y, w) -> edge from x to y having weight w
{ 0, 1, 2 }, { 1, 3, 4 }, { 0, 3, 6 }
};
// Set maximum number of nodes in the graph
int N = 5;
// let source be vertex 0
int source = 0;
// run Bellman Ford Algorithm from given source
BellmanFord(edges, source, N);
return 0;
}
答案 0 :(得分:0)
更抽象地看待这个问题,您可以找到最小的东西,并且想要对其进行更改以将其他所有同样小的东西返回。 (当寻找最大的东西时,同样的原则也适用。不过,坚持“最小”的做法有助于做出更简单的解释。)
许多用于查找极端事物的算法在某些方面要求“是A比B更极端”。例如,您可能会看到类似以下的代码:
if ( A < B )
smallest = A;
请注意,它如何忽略联系(A == B
)的方式与忽略更差结果(A > B
)的方式相同。因此,您只会得到返回的最佳结果中的第一个。所以这是要改变的事情。但是,您不能简单地将A < B
更改为A <= B
,因为在平局的情况下将B
替换为A
,就像在{{1 }}是更好的结果。 (返回的最佳结果只有 last 。)这三种情况(小于,等于和大于)需要分别处理。
另一个要看的方面是如何跟踪最小的事物。上面的代码段表明A
与smallest
具有相同的类型;这不足以跟踪多个解决方案。您可能需要一个容器来跟踪解决方案。 A
可能是一个合理的选择。
将它们放在一起,上面的代码可能会变成类似以下内容(在更改vector
的声明之后):
smallest
如何将其应用于Bellman-Ford?
幸运的是,代码的关键部分相对容易,因为有注释记录在其中。较难的部分是更改代码以跟踪多个结果,因为找到较短的路径时会更新两个数据。看来if ( A < B ) {
smallest.clear();
smallest.push_back(A);
}
else if ( A == B ) {
smallest.push_back(A);
}
是需要扩展的数据。这是它的新声明:
parent
这使用空向量代替vector< vector<int> > parent (N);
来表示“无父”。现在可以成为最短路径的检查
-1
这与常规方法略有不同,因为没有“ if (distance[u] != INT_MAX) {
// if the distance to the destination v can be
// shortened by taking the edge u-> v
if (distance[u] + w < distance[v])
{
// update distance to the new lower value
distance[v] = distance[u] + w;
// forget the previous parent list.
parent[v].clear();
}
// if u-> v is a way to get the shortest
// distance to the destination v.
if (distance[u] + w == distance[v])
{
// add u as a possible parent for v
parent[v].push_back(u);
}
}
”。这是相同的逻辑,只是排列方式有所不同。请注意,当输入第一个else
子句时,距离矢量会更新,因此也要输入第二个if
子句。
我认为处理找到的路径是一个单独的(而不是琐碎的)问题,因此我将留给您了解如何更新if
。不过,我将给出一个在接收新结果的同时保留旧输出(只是最短路径的第一个)的版本。这并不是建议,只是说明新数据结构与旧数据结构有关。
printPath()