如何找到两个最广泛分离的节点之间的距离

时间:2008-10-04 05:40:34

标签: java algorithm graph-theory

我正在研究前几年的ACM编程竞赛问题,试图更好地解决图形问题。

我现在正在研究的是我给出了任意数量的无向图节点,它们的邻居以及连接节点的边缘的距离。我需要的是距离彼此最远的两个节点之间的距离(重量距离,而不是距节点数#)。

现在,我确实有以下形式的Dijkstra算法:

// Dijkstra's Single-Source Algorithm
private int cheapest(double[] distances, boolean[] visited)
{
        int best = -1;
        for (int i = 0; i < size(); i++)
        {
                if (!visited[i] && ((best < 0) || (distances[i] < distances[best])))
                {
                        best = i;
                }
        }
        return best;
}

// Dijkstra's Continued
public double[] distancesFrom(int source)
{
        double[] result = new double[size()];
        java.util.Arrays.fill(result, Double.POSITIVE_INFINITY);
        result[source] = 0; // zero distance from itself
        boolean[] visited = new boolean[size()];
        for (int i = 0; i < size(); i++)
        {
                int node = cheapest(result, visited);
                visited[node] = true;
                for (int j = 0; j < size(); j++)
                {
                        result[j] = Math.min(result[j], result[node] + getCost(node, j));
                }

        }
        return result;
}

通过这个实现,我可以给它一个特定的节点,它将给我一个列表,列出该节点的所有距离。所以,我可以抓住距离列表中的最大距离,但我无法确定任何特定节点是两端最远的两个节点之一。

所以我能想到的唯一解决方案是在每个节点上运行这个Dijkstra算法,遍历每个返回的距离列表并寻找最大距离。在耗尽每个节点返回它的距离列表之后,我应该具有任意两个节点之间的最大距离的值(两个最广泛分离的村庄之间的“道路”距离)。必须有一个更简单的方法来做到这一点,因为这似乎在计算上非常昂贵。问题是可能有多达500个节点的样本输入,所以我不希望它花费太长时间。这是我应该怎么做的?

以下是问题的示例输入:

总节点数:5

边缘:
节点2 - 连接 - 节点4.距离/重量25
节点2 - 连接 - 节点5.距离/重量26
节点3 - 连接 - 节点4.距离/重量16
节点1 - 连接 - 节点4.距离/重量14

此示例输入的答案是“67英里”。这是两个分布最广的村庄之间的道路长度。

那么我应该如何描述或者是否有一种更简单且计算成本更低的方式?

6 个答案:

答案 0 :(得分:3)

看起来你可以使用以下任何一个:

我不能给你很多关于他们的指导 - 我不是专家。

答案 1 :(得分:2)

所以Dijkstra的实现运行O(VlogV + E),使您的方法具有大致V ^ 2logV + VE的复杂性。见DADS。但也许更直观的是运行所有pairs shortest path算法之一,如Floyd-Warshall或Johnsons。不幸的是,对于密集图,它们都大致为O(V ^ 3)(接近E = V ^ 2的完整图)。

答案 2 :(得分:1)

这是Roads in the North问题吗?

答案 3 :(得分:0)

您可以按照以下方式使用Dijkstra的实施:

  1. 选择一个随机节点,(a),从节点a运行Dijkstra,并从中找到最远的节点。将该节点标记为节点b。
  2. 从节点b开始再次运行Dijkstra,并从中找到最远的节点。将该节点标记为节点c。
  3. 我没有这方面的证据,但我认为b和c将是最远的节点。您可能需要再运行一次(我还在考虑它)。

答案 4 :(得分:0)

将边权重乘以-1,找到新图上的最短路径。这将是原始图表上最长的路径

答案 5 :(得分:0)

如果你想要最长的最短路径

sup i,j {inf i,j {n:n = i和j之间路径的长度}}

你应该考虑像其他人一样提到的所有节点最短路径算法,如Flyod-Warshall。这将是O(V ^ 3)的顺序。

如果您想要最长的路径

sup i,j {n:n = i和j之间路径的长度}

您可以尝试使用Midhat的想法。 (这实际上和评论中指出的原始问题一样复杂)我建议用1 / w来反转权重,保留正权重,假设原始权重是严格正数。

在处理负权重时,您可能想要查找的另一种算法是Bellman和Ford的算法