Algorithm 从邻接列表计算每个顶点的可达性

Algorithm 从邻接列表计算每个顶点的可达性,algorithm,graph-theory,graph-algorithm,floyd-warshall,transitive-closure,Algorithm,Graph Theory,Graph Algorithm,Floyd Warshall,Transitive Closure,给定DAG的邻接列表Map,我想计算每个顶点的可达性(即,如果存在从u到v的路径) 静态映射可达性(Map adjList){} 我知道在O(V^3) //将邻接列表转换为邻接矩阵矩阵 无效可达性(布尔mat[][]){ 最终int N=材料长度; 对于(int k=0;k

给定DAG的邻接列表
Map
,我想计算每个顶点的可达性(即,如果存在从u到v的路径)

静态映射可达性(Map adjList){}

我知道在
O(V^3)

//将邻接列表转换为邻接矩阵矩阵
无效可达性(布尔mat[][]){
最终int N=材料长度;
对于(int k=0;k
但是我有一个稀疏图(和一个邻接列表),那么最快的方法是什么呢?

一个
O(V*(V+E))
解决方案可以是从图中的每个节点执行一个简单的操作,并计算其可达性集。假设java中的
| E | 2^V//Map
i=n-1
而(i>=0):
设v为v[i]中的顶点
已连接[v]。添加(v)
对于每个边(v,u):
//因为图是DAG,我们按相反的顺序处理
//已连接[u]的值已知,因此我们可以使用它。
已连接[v]。添加所有(已连接[u])
这里是一个简单的Scala中的
O(|V | | E |)
解决方案(基本上,对于每个顶点,执行DFS):


这里的可执行版本:

您能再解释一下这行
connected(v)=union{connected(u)| for all edge(v,u)}u{v}
吗?谢谢@对于每个节点
u
,您都有一组其他节点连接到它,并用
连接(u)
表示。将所有传出边缘从
v
中取出,并合并连接到它们的节点,然后在末尾添加
v
。这将为您提供一组连接到
v
的已连接节点。但是,我不需要递归地进行联合吗??你能用一些伪代码更新答案吗…@wrick你熟悉动态编程吗?是的,但我不明白-什么是关联的。它最初是一张空地图吗?
// Convert adjList to adjacency matrix mat
void reachability(boolean mat[][]) {
  final int N = mat.length;
  for (int k = 0; k < N; k++)
    for (int i = 0; i < N; i++)
      for (int j = 0; j < N; j++)
        mat[i][j] |= mat[i][k] && mat[k][j];
}
V = [v0,v1,...,vn-1]
V = topological_sort(V) //O(V+E)
connect = new Map:V->2^V //Map<Vertex,Set<Vertex>> in java
i = n-1
while (i >= 0):
   let v be the vertex in V[i]
   connected[v].add(v)
   for each edge (v,u):
      //since the graph is DAG, and we process in reverse order
      //the value of connected[u] is already known, so we can use it.
      connected[v].addAll(connected[u])
type AdjList[A] = Map[A, Set[A]]

def transitiveClosure[A](adjList: AdjList[A]): AdjList[A]  = {
  def dfs(seen: Set[A])(u: A): Set[A] = {
    require(!seen(u), s"Cycle detected with $u in it")
    (adjList(u) filterNot seen flatMap dfs(seen + u)) + u
  }
  adjList.keys map {u =>
    u -> dfs(Set.empty)(u)  
  } toMap
}