Directed Graphs
Shortest directed cycle. Given a digraph G, design an efficient algorithm to find a directed cycle with the minimum number of edges (or report that the graph is acyclic). The running time of your algorithm should be at most proportional to V(E+V) and use space proportional to E+V, where V is the number of vertices and E is the number of edges.
Hint: run BFS from each vertex.
参考 ShortestDirectedCycle.java。
Hamiltonian path in a DAG. Given a directed acyclic graph, design a linear-time algorithm to determine whether it has a Hamiltonian path (a simple path that visits every vertex), and if so, find one.
Hint: topological sort.
先计算出该图的拓扑排序序列,再判断该序列中任意两个连续的结点是否相连,若是则存在哈密顿回路,且结点顺序正是拓扑序列,若不是则不存在哈密顿回路。
import edu.princeton.cs.algs4.Digraph;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class Hamiltonian {
private List<Integer> path;
private boolean marked[];
private boolean hasPath;
private Digraph G;
public Hamiltonian(Digraph G) {
path = new ArrayList<>();
marked = new boolean[G.V()];
hasPath = true;
this.G = G;
for (int v = 0; v < G.V(); v++) {
if (!marked[v]) {
dfs(v);
}
}
Collections.reverse(path);
for (int i = 0; i < path.size() - 1; i++) {
int v = path.get(i);
int w = path.get(i + 1);
boolean found = false;
for (int u : G.adj(v)) {
if (u == w) {
found = true;
break;
}
}
if (!found) {
hasPath = false;
break;
}
}
}
public boolean hasPath() {
return hasPath;
}
public Iterable<Integer> getPath() {
return path;
}
private void dfs(int v) {
marked[v] = true;
for (int w : G.adj(v)) {
if (!marked[w]) {
dfs(w);
}
}
path.add(v);
}
}
Reachable vertex.
- DAG: Design a linear-time algorithm to determine whether a DAG has a vertex that is reachable from every other vertex, and if so, find one.
- Digraph: Design a linear-time algorithm to determine whether a digraph has a vertex that is reachable from every other vertex, and if so, find one.
Hint (DAG): compute the outdegree of each vertex.
Hint (digraph): compute the strong components and look at the kernel DAG (the digraph that results when you contract each strong component to a single vertex).
DAG:对于有向无环图来说,如果存在一个点X,图中其他所有点都有路径到达X,那么X的出度必为0。如果不为0,假设X能够到达点Y,而Y又有路径到达X,就构成了环,与DAG的前提矛盾。找到出度为0的点后(可能多个),在图 G G G的逆向图 G R G^R GR中判断能否从X到达所有的点(一次DFS即可),如果能说明X就是要找的点。
Digraph:对于更普遍情况的有向图,先利用Kosaraju方法标识出所有强连通分量,id最小的强连通分量中的所有点就是候选点。针对每个候选点X,在图 G G G的逆向图 G R G^R GR中判断能否从X到达所有的点(一次DFS即可),如果能说明X就是要找的点。