【问题标题】:revisiting nodes during DFS and controlling infinite cycles在 DFS 期间重新访问节点并控制无限循环
【发布时间】:2010-01-03 20:16:43
【问题描述】:

我正在通过以下方式在加权有向图上实现 DFS:

    public class DFSonWeightedDirectedGraph {

    private static final String START = "A";
    private static final String END = "C";
    private int pathLength = 0;
    private int stops = 0;

    public static void main(String[] args) {
        //this is a directed weighted graph
        WeightedDirectedGraph graph = new WeightedDirectedGraph();
        graph.addEdge("A", "B", 5);
        graph.addEdge("A", "D", 5);
        graph.addEdge("A", "E", 7);
        graph.addEdge("B", "C", 4);
        graph.addEdge("C", "D", 8);
        graph.addEdge("C", "E", 2);
        graph.addEdge("D", "C", 8);
        graph.addEdge("D", "E", 6);
        graph.addEdge("E", "B", 3);

        LinkedList<String> visited = new LinkedList<String>();
        visited.add(START);
        new DFSonWeightedDirectedGraph().depthFirst(graph, visited);
    }

    private void depthFirst(WeightedDirectedGraph graph, LinkedList<String> visited) {
        Collection<Map.Entry<String, Integer>> nodes = graph.adjacentNodes(visited.getLast());      
        // examine adjacent nodes
        for (Map.Entry<String, Integer> node : nodes) {
            if (visited.contains(node.getKey())) {
                continue;
            }
            if (node.getKey().equals(END)) {
                visited.addLast(node.getKey());  
                pathLength += node.getValue();
                stops += 1;
                printPath(visited);
                visited.removeLast();
                pathLength -= node.getValue();
                stops -= 1;
                break;
            }
        }
        // recursion
        for (Map.Entry<String, Integer> node : nodes) {
            if (visited.contains(node.getKey()) || node.getKey().equals(END)) {
                continue;
            }
            visited.addLast(node.getKey());
            pathLength += node.getValue();
            stops += 1;
            depthFirst(graph, visited);
            visited.removeLast();
            pathLength -= node.getValue();
            stops -= 1;
        }
    }

    private void printPath(LinkedList<String> visited) {
        for (String node : visited) {
            System.out.print(node);
            System.out.print(" ");
        }
        System.out.println("[path length: "+pathLength +
                " stops made: "+ stops+"]");
    }
}

我需要修改上述内容以允许在搜索源节点和目标节点之间的所有路径期间循环。为了避免无限循环,可以根据“停止”的次数或从源头经过的最大允许距离设置条件以终止搜索。

通过这种方式,例如,我可以找到从 A 开始到 D 结束且恰好有 5 个停靠点的行程数:一种解决方案可以是 ABCDCD。或者,我可以找到从 D 到 D 距离小于 40 的不同路线的数量:一些解决方案是 DECD、DEBCD、DCDCD。

我的问题是我不确定如何创建保持主算法搜索的逻辑,同时逃避保证不会到达目标节点的无限搜索循环。

假设我想从 A 到 D。一个可能的死循环可能是 ABCEBCEBCEB....(到无穷大)。我基于停靠点数或总行驶距离的条件可以终止此循环,但也将结束整个搜索,否则可能会找到正确的路径 ABCDCDCDCD,当满足任一预设条件时,它将正确终止。

感谢您的任何想法。

【问题讨论】:

    标签: java graph cycle depth-first-search


    【解决方案1】:

    我认为您需要动态设置截止点/距离。例如,对于“A 到 D 正好 5 个停止”的问题,将截止值设置为 5 个停止将在所有循环达到 6 个停止时终止它们。如果您将截止距离设置为 40,则问题“D 到 D 的距离小于 40”也是如此。

    使用“可访问性矩阵”可以更早地切断一些循环,即如果存在从 i 到 j 的路径,则 a(i, j) = 1 或否则 a(i, j) = 0 的矩阵.您可以通过首先找到图的强连通分量来构造这样的矩阵(使用类似this 的算法)。
    然后你可以拒绝一个搜索周期,如果目标节点不能从当前节点访问,即 a(current, target) = 0。

    【讨论】:

    • 感谢您的回复。我想知道,假设有一条从 A 到 D 的路径,因此 M(a,d) = 1,其中 M 是可访问性矩阵,如何从 A 到达 D 而不会陷入中间某处的无限循环? (即 ABCEBCEBCEB... 到 inf - ABCDCDCD 是有效结果)如果我根据停止或距离终止,我会失去整个搜索权吗?
    • 如果 M(A, D) = M(B, D) = M(C, D) = M(E, D) = 1,那么你不能用这个来停止无限循环方法(这是不对的,因为 ABCEBCD 是一个有效的解决方案)。在这种情况下,您只能使用停止的截止点来停止循环。例如,如果您需要找到所有 en.wikipedia.org/wiki/Depth-limited_search
    • 谢谢。基本上,我正在尝试看看是否有更简单的方法。根据我上面的代码,如果我删除检查重新访问节点的 if 语句 - 或者只是注释掉“继续”关键字,那么我有一个无限循环,它会打印到控制台上,如下所示:ADEBC (...) DEBCDC [路径长度:4444 个停靠点:846]。但仍然难以理解机制。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-05-15
    • 1970-01-01
    • 2022-01-08
    • 2021-03-24
    • 1970-01-01
    • 2015-09-13
    • 1970-01-01
    相关资源
    最近更新 更多