.
网络上只有关于深度优先搜索(DFS)、A*或Dijkstra的参考资料,但我认为它们在这种情况下不起作用。
有人知道如何解决吗?
.
伪代码:
int source;
int sink;
int nVerts;
bool inAllPaths[nVerts]; // init to all true
bool visited[nVerts]; // init to all false
stack<int> path; // init empty
bool dfs(int u)
if (visited[u])
return;
if (u == sink)
for i = 0 to nVerts-1
if !stack.contains(i)
inAllPaths[i] = false;
return true;
else
visited[u] = true;
stack.push(u);
foreach edge (u, v)
dfs(v);
stack.pop();
visited[u] = false;
return false;
main()
dfs(source);
// inAllPaths contains true at vertices that exist in all paths
// from source to sink.
然而,这个算法并不是非常高效。例如,在n个顶点的完全图中(所有顶点都与其他顶点相连),路径的数量将为n!(n的阶乘)。
更好的算法是分别检查每个顶点在每条路径中是否存在。对于每个顶点,尝试找到一条从源到汇的路径,而不经过该顶点。如果找不到这样的路径,则说明该顶点出现在每条路径中。
伪代码:
// Using the same initialisation as above, but with a slight modification
// to dfs: change the foreach loop to
foreach edge (u, v)
if (dfs(v))
return true; // exit as soon as we find a path
main()
for i = 0 to nVerts-1
set all visited to false;
if (inAllPaths[i])
visited[i] = true;
if (dfs(source))
inAllPaths[i] = false;
visited[i] = false;
不幸的是,当搜索路径时,这仍然具有指数最坏情况。您可以通过将搜索更改为广度优先搜索来解决此问题。如果我没有错的话,这应该给您 O(VE) 的性能。
我知道已经有一段时间了,但我来这里寻找一些在SQL或Java中查找所有路径(不仅仅是最短路径)的算法,我找到了以下三个(我只是发布它们以保持概念的组织):
Java
http://introcs.cs.princeton.edu/java/45graph/AllPaths.java.html(依赖项:Graph、ST、Set、In,可在http://introcs.cs.princeton.edu/java/45graph/中找到)
SQL(PostgreSQL)。
检查WITH RECURSIVE transitive_closure(a, b, distance, path_string) AS
http://techportal.inviqa.com/2009/09/07/graphs-in-the-database-sql-meets-social-networks/
PL/SQL(Oracle)
https://forums.oracle.com/forums/thread.jspa?threadID=2415733
select pth as "Path", distance as "Distance"
from (
select connect_by_root(n1) || sys_connect_by_path(n2,'>') pth ,n2, level as distance
from -- Edge List Table
(select 'A' n1,'B' n2 from dual
union all select 'A','C' from dual
union all select 'B','C' from dual
union all select 'B','D' from dual
union all select 'D','G' from dual
union all select 'C','G' from dual
union all select 'D','I' from dual
union all select 'C','E' from dual
union all select 'E','F' from dual
union all select 'F','G' from dual
union all select 'F','H' from dual
) links
start with n1='A'
connect by nocycle prior n2=n1)
where n2 = 'G';
结果:
Distance Path
3 A>B>C>G
5 A>B>C>E>F>G
3 A>B>D>G
2 A>C>G
4 A>C>E>F>G
n1...开头的行
和n2...所在的行
,则查询将返回所有图形中的所有路径。For each node k in subtree s,
if k has an edge to a non-blue node x
then k is true and x is true.
同时,将v标记为true。最后,我会使用递归函数到达叶子节点。例如:
function(node n){
if(n = null)
return false
if(function(n.left) or function(n.right) or n.val){
n.val = true
return true
}
else
return false
}
所有标记为真的节点将是从u到v路径中的节点。运行时间最多为(顶点数+边数),因为DFS =(V + E),for循环最多为(V),递归最多为(V)。
从起始节点开始运行深度优先搜索,并保持自己的堆栈,以告诉您在任何给定时间看到了哪些节点。注意循环:当您看到一个节点两次时,您就有了一个循环,并且必须中止当前路径。注意不要访问节点的父节点,以避免长度为1的循环(向DFS函数添加一个parent
参数将有所帮助)。
然后,当您到达目标节点时,请输出堆栈的内容。
一旦DFS完成,您将拥有所有路径。
如果一个顶点从A到B的路径上是可达的,并且B也是从它可达的,则该顶点就在该路径上。
因此:从A开始进行泛洪填充。标记所有这些顶点。 从B开始进行泛洪填充,并按相反方向跟随边缘。你遇到的所有标记顶点都是解决方案的一部分。