给定图形,我们如何确定是否存在顶点v,所有其他顶点都可以从该顶点v到达。算法应该尽可能高效。
如果我们检查给定的顶点,我知道怎么做;我们可以在反向图上做dfs。但对于这个问题,对图中的每个顶点执行它似乎效率低下。
有更好的方法吗?
感谢。
答案 0 :(得分:11)
使用Kosaraju's algorithm及时查找图表中强关联的组件O(|V|+|E|)
。如果然后将每个组件“缩小”到单个节点,则会留下有向非循环图。存在一个顶点,当且仅当DAG中有一个具有in-degree 0的顶点时,才能到达所有其他顶点。这是您正在寻找的顶点 - 所谓的“母顶点”。
注意:这个答案最初建议使用Tarjan的算法。 Tarjan的速度可能会快一些,但它也比Kosaraju的复杂一点。
答案 1 :(得分:3)
通过采用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);
}
上述算法需要O(V + E)时间来解决问题。
答案 2 :(得分:1)
我刚刚发明了以下算法。
这个想法是,因为任何顶点都应该可以从母顶点到达,所以我们可以向上采取任意路径,直到我们不能更高。
这样我们只检查可以到达起始顶点的强连通分量。如果有很多强连通组件的度数为0,那么这将是Andy算法的明显优势。
答案 3 :(得分:0)
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);
}
}
}
}