Algorithm 在有向图中查找可以到达所有其他顶点的顶点
给定一个有向图,我们如何确定是否存在一个顶点v,所有其他顶点都可以从该顶点v到达。算法应该尽可能高效 我知道如何做,如果我们正在检查一个给定的顶点;我们可以在反向图上进行dfs。但对于这个问题,对图中的每个顶点都这样做似乎效率低下 有更好的方法吗?用于在时间Algorithm 在有向图中查找可以到达所有其他顶点的顶点,algorithm,graph,Algorithm,Graph,给定一个有向图,我们如何确定是否存在一个顶点v,所有其他顶点都可以从该顶点v到达。算法应该尽可能高效 我知道如何做,如果我们正在检查一个给定的顶点;我们可以在反向图上进行dfs。但对于这个问题,对图中的每个顶点都这样做似乎效率低下 有更好的方法吗?用于在时间O(|V|+|E|)中查找图的强连通分量。如果将每个组件“收缩”到一个节点,则将留下一个有向无环图。存在一个顶点,当且仅当DAG中只有一个顶点的阶数为0时,可以从该顶点到达所有其他顶点。这是您正在寻找的顶点-所谓的“母顶点” 注:此答案最初建
O(|V|+|E|)
中查找图的强连通分量。如果将每个组件“收缩”到一个节点,则将留下一个有向无环图。存在一个顶点,当且仅当DAG中只有一个顶点的阶数为0时,可以从该顶点到达所有其他顶点。这是您正在寻找的顶点-所谓的“母顶点”
注:此答案最初建议使用Tarjan算法。Tarjan的可能要快一点,但也比Kosaraju的要复杂一点 我刚刚发明了以下算法
- 从任意顶点开始,并将其标记为“已访问”
- 在图中“向上”转到任意父顶点,并将其标记为“已访问”
- 跟踪堆栈上访问的顶点
- 如果到达的顶点没有父顶点,请检查它是否确实是所有其他顶点都可以从中到达的顶点李>
- 到达已访问的顶点V时:
- 不要将访问的顶点V添加到堆栈中。将上一个顶点标记为强连接组件的“端点”
- 沿着堆栈向下移动,直到到达已访问的顶点V。 一路上,您可以删除所有“结束”和“开始”标记。 如果最后移除的标记是“开始”标记,则将V标记为“开始”,否则不要标记李>
- 再次从堆栈顶部开始向下移动,直到找到具有未访问父顶点的顶点(并继续执行算法的第一步),或者直到到达标记为“开始”的顶点,并检查该顶点是否确实是可以访问所有其他顶点的母顶点
这样,我们只检查可以到达起始顶点的强连接组件。如果存在大量阶数为0的强连通组件,这将是Andy算法的一个明显优势。可以从Kosaraju的强连通组件算法中找到解决方案。这一想法基于以下事实: 如果存在一个顶点(或多个顶点),所有其他顶点都可以从该顶点到达,则该顶点在DFS遍历中的完成时间最长。 因此,解决方案如下所示:
// Utility function to find mother vertex
//(vertex from which all other vertices are reachable)
public void findMotherVertex() {
int motherVertex=0;
for (int i=0;i<G.V();i++) { //G.V() would return the no. of vertices in the graph
if (!marked[i]) { //marked - boolean array storing visited vertices
dfs(i);
motherVertex=i;
}
}
//Check for this vertex if all other vertices have been already visited
//Otherwise no mother vertex exists
for (int i=0;i<G.V();i++) {
if (!marked[i])
return false;
}
System.out.println("Desired vertex is : " + motherVertex);
}
//查找母顶点的实用函数
//(所有其他顶点均可从中访问的顶点)
public void findMotherVertex(){
int=0;
对于(inti=0;iimportjava.util.*;
公共类FindMotherVertex{
公共静态void main(字符串[]arg){
List edges=Arrays.asList(
新边(0,1),新边(0,2),
新边(1,3),
新边(4,1),
新边(5,2),新边(5,6),
新边(6,4),
新边(6,0)
);
findMotherVertex(图);
}
公共静态void findMotherVertex(图形){
int=0;
布尔值[]已访问=新布尔值[7];
对于(int i=0;i=0;i--){
int u=list.get(i);
如果(!访问[u]);
堆栈推送(u);
}
}
}
静态类图{
//表示辅助列表的列表列表列表
List adj=新的ArrayList();
//构造图的构造函数
公共图(列出边){
//为邻接列表分配内存
对于(int i=0;i
在稠密图上,你可以做一个Floyd Warshall,然后查找一行所有的。这个问题有用吗?@Jake是一篇帖子,要求一个可以从其他每个顶点到达的顶点(如标题所示),或者一个可以从其他每个顶点到达的顶点(如帖子本身)?一个顶点,每个其他顶点最多可以到达一个顶点,或者正好可以到达一个顶点?你是对的,正好是一个-如果图中没有处于零度的顶点,它将包含一个循环。编辑。不是学究式的,但你的意思是“没有处于0度”而不是“处于0度”):答案很好,已经投了赞成票。不是吗?除非我遗漏了什么,否则绝对是零度。认为是我感到困惑,所以忽略上面的内容。但困惑并不是因为一个坏的原因。标题是:找到所有其他顶点都可以到达的顶点;和1和2是连接的,而3没有任何传入/传出边。您是第一个使用moder_vertex=3的for循环,并且还将标记所有访问(或标记)的三条边。那么第二个for循环将不会返回false。最后,我们将得到母亲指数=3,这是不正确的。不是吗!
import java.util.*;
public class FindMotherVertex {
public static void main(String[] arg) {
List<Edges> edges = Arrays.asList(
new Edges(0, 1), new Edges(0, 2),
new Edges(1, 3),
new Edges(4, 1),
new Edges(5, 2), new Edges(5, 6),
new Edges(6, 4),
new Edges(6, 0)
);
findMotherVertex(graph);
}
public static void findMotherVertex(Graph graph) {
int motherVertex = 0;
boolean[] visited = new boolean[7];
for (int i=0;i<7;i++) {
if (visited[i] == false) { //marked - boolean array storing visited vertices
DFS(graph,i,visited);
motherVertex= i;
}
}
//Check for this vertex if all other vertices have been already visited
//Otherwise no mother vertex exists
for (int i=0;i<6;i++) {
if (!visited[i]){ visited[i] = false;}
}
System.out.println("Mother vertex is : " + motherVertex);
}
public static void DFS(Graph graph, int v,boolean[] visited) {
//create a stack used to do DFS
Stack<Integer> stack = new Stack<>();
stack.add(v);
//Run While queue is empty
while (!stack.isEmpty()) {
//Pop vertex from stack
v = stack.pop();
if (visited[v])
continue;
visited[v] = true;
System.out.print("(" + v + ")" + "===>");
// do for every edge
List<Integer> list = graph.adj.get(v);
for (int i = list.size() - 1; i >= 0; i--) {
int u = list.get(i);
if (!visited[u]) ;
stack.push(u);
}
}
}
static class Graph {
//List of List to represent Adajacency List
List<List<Integer>> adj = new ArrayList<>();
//Constructor to construct Graph
public Graph(List<Edges> edges) {
//Allocate memory for adjacency List
for (int i = 0; i < edges.size(); i++) {
adj.add(i, new ArrayList<>());
}
//Add edges to the undirected Graph
for (Edges curr : edges) {
adj.get(curr.src).add(curr.desc);
}
}
}
}