问题描述
给定一个图中间两个节点,我们需要返回这两个节点之间所有的simple path。什么是simple path呢?就是图中间不包含有重复节点的路径。
问题分析
对于这个问题,我们比较容易想到一些和其他问题近似的地方。比如说给定两个节点要判断它们是否连通。而且在连通的时候我们可以找到一条这两个节点之间的路径。对于这个相对简化的问题来说,我们可以通过图的某种遍历方式,每次遍历的时候记录节点之间的访问关系,一直到目标节点。
对于我们这个问题本身来说,它和那个简化的问题不一样。因为这里要列出所有到达目标节点的路径。对于两个节点之间,它们可能有多个路径是连通的。比如说节点a和c之间构成一个如下的图:
那么,从上图中我们可以看到从a到c的路径可以有a-> c,也有a --> b --> c。假设我们用前面的深度优先遍历来访问图的时候,如果我们一开始是走的路径a --> c,那么这就是找到了一个路径了。而要找到另外一个路径,我们就需要将前面访问过的c节点重置一下。因为一般的情况下我们遍历时会将访问过的节点做一个标记,而这里因为有多个路径要记录,我们需要将达到目的节点的路径重置。这样下次访问的时候才能不会有可选的路径被覆盖。
因此在这里我们就可以发现,我们需要在函数递归调用返回的时候将当前访问的节点重置。也就是在递归调用回溯的阶段要做的事情。这样,我们在深度优先遍历查找的时候设置两个参数v, t。一个表示当前节点,一个表示目标节点。当当前节点v == t的时候,则说明找到了一个路径,我们需要将当前路径里的值给记录下来。而为了保存这个访问的记录,我们需要用一个栈来保存每次走过的节点。
按照前面所描述的,在调用返回的时候,我们需要进行重置,也就是将当前节点从栈里弹出来,然后当前节点的访问标识设置回去。
这样,我们可以得到一个如下的实现:
public class AllPaths { private boolean[] onPath; private Stack<Integer> path; private int List<List<Integer>> result; private int numberOfPaths; public AllPaths(Graph g, int s, int t) { onPath = new boolean[g.vertices()]; path = new Stack<>(); result = new ArrayList<>(); dfs(g, s, t); } private void dfs(Graph g, int s, int t) { path.push(v); onPath[v] = true; if(v == t) { // process current path processCurrentPath(); numberOfPaths++; } else { for(int w : g.adj(v)) { if(!onPath[w]) dfs(g, w, t); } } path.pop(); onPath[v] = false; } private void processCurrentPath() { List<Integer> list = new ArrayList<>(); list.addAll(path); Collections.reverse(list); result.add(list); } public int numberOfPaths() { return numberOfPaths; } public List<List<Integer>> allPaths() { return result; } }
总的来说,上述的代码无非就是深度优先遍历这个递归函数调用的变体。在函数递归调用结束开始回溯的时候,我们可以有一些巧妙的应用。这样就能将所有合适的路径给记录下来。
总结
利用一些函数的递归调用和回溯关系,我们不仅可以找到图里面两个节点之间所有可能的路径。同时在其他很多问题的典型应用中也得到很好的利用。比如n皇后问题里递归回溯的推导利用,比如求树中间两个节点的最低公共父节点。这里的应用很巧妙,值得深入分析。
参考材料
http://algs4.cs.princeton.edu/41graph/AllPaths.java.html
相关推荐
A multistage graph is a graph (1) G=(V,E) with V partitioned into K >= 2 disjoint subsets such that if (a,b) is in E, then a is in Vi , and b is in Vi+1 for some subsets in the partition; and (2) | ...
Note that specifying the same folder as output directory (like in this example) will overwrite the initial graph with a new one containing additional information. Since we do some vertex sorting in ...
所有顶点对间最短路 All-pairs shortest paths 1.6.2.2.1. 基本算法 Basic algorithms 1.6.2.2.1.1. Floyd-Warshall 1.6.2.2.1.2. Johnson 1.6.3. 网络流 Flow network 1.6.3.1. 最大流 Maximum flow 1.6.3.1.1. ...
10.2 Enumerating All Loopless Paths with the Latin Multiplication Algorithms 161 10.3 Shortest Path: Djsktra Algorithm 165 10.4 Least Cost Path 165 10.5 Least Trouble Path 165 10.6 The Best Flow ...
Hence, it becomes possible for the attacker to issue a command to all the nodes, that target a single node (for example, all nodes in the botnet might be commanded by the attacker to send a TCP SYN ...
2.15 Graph structures and paths 2.16 Search 2.17 Animal identification game 2.18 Clauses as data 2.19 Actions and plans 3. How Prolog Works 3.1 Prolog derivation trees, choices and unification ...
"checking out paths out of the index and/or a tree-ish to work on advancing the current history" out of the single "git checkout" command. * "git branch --list" learned to always output the ...
Set y-axis to draw only whole numbers in the legend to make the graph easier to interpret. Respect command-line arg kafkaOffsetForceFromStart, starting consumer offset listener clients from the ...
Chapter 25 - All-Pairs Shortest Paths Chapter 26 - Maximum Flow Part VII - Selected Topics Chapter 27 - Sorting Networks Chapter 28 - Matrix Operations Chapter 29 - Linear Programming ...
The book covers a broad range of algorithms in depth, yet makes their design and analysis accessible to all levels of readers. Each chapter is relatively self-contained and can be used as a unit of ...
Note: If you use a symbol Foo in your source file, you should bring in a definition for Foo yourself, either via an #include or via a forward declaration. Do not depend on the symbol being brought in ...
Chapter 25 - All-Pairs Shortest Paths Chapter 26 - Maximum Flow Part VII - Selected Topics Chapter 27 - Sorting Networks Chapter 28 - Matrix Operations Chapter 29 - Linear Programming ...
Chapter 25 - All-Pairs Shortest Paths Chapter 26 - Maximum Flow Part VII - Selected Topics Chapter 27 - Sorting Networks Chapter 28 - Matrix Operations Chapter 29 - Linear Programming ...
6. 题目30:连接所有路径中的节点 (Connect All Paths in the Graph) 考察图的遍历,通常使用深度优先搜索(DFS)或广度优先搜索(BFS)来找出所有可能的路径。 7. 题目3:无重复字符的最长子串 (Longest Substring ...
25 All-Pairs Shortest Paths 620 25.l Shortest paths and matrix multiplication 622 25.2 The Floyd-Warshall a1gorithm 629 25.3 Johnson's algorithm for sparse graphs 636 26 Maximum Flow d43 26.l Flow ...
Chapter 25 - All-Pairs Shortest Paths Chapter 26 - Maximum Flow Part VII - Selected Topics Chapter 27 - Sorting Networks Chapter 28 - Matrix Operations Chapter 29 - Linear Programming ...
new_paths = find_all_paths(graph, node, end, path) for newpath in new_paths: paths.append(newpath) return paths ``` ##### 最短路径 对于图中的最短路径问题,可以采用改进的 DFS 方法,通过记录每一步...