1. 联通分量
- 统计一个图中联通分量个数
- 判断两点是否联通
- 求每个联通分量中包含点编号
import java.util.ArrayList;
//Connected Component —— 联通分量
public class CC {
private Graph G;
private int[] visited; //将 boolean型改为 int型
private int cccount = 0;
CC(Graph G) {
this.G = G;
visited = new int[G.V()];
for (int i = 0; i < visited.length; i++) {
visited[i] = -1;
}
//解决非连通图的遍历问题
for (int v = 0; v < G.V(); v++) {
if (visited[v] == -1) {
dfs(v, cccount);
cccount++;
}
}
//dfs(0);
}
private void dfs(int v, int ccid) {
visited[v] = ccid;
for (int w : G.adj(v)) {
if (visited[w] == -1)
dfs(w, ccid);
}
}
public int count() {
// for (int i = 0; i < visited.length; i++) {
// System.out.print(visited[i] + " ");
// }
// System.out.println();
return cccount;
}
//两个顶点是否联通
public boolean isConnected(int v, int w) {
G.validateVertex(v);
G.validateVertex(w);
return visited[v] == visited[w];
}
//每个联通分量里面包含节点编号
public ArrayList<Integer>[] components() {
ArrayList<Integer>[] res = new ArrayList[cccount]; //有cccount个联通分量
for (int i = 0; i < res.length; i++) { //编号[0 ~ cccount-1]
res[i] = new ArrayList<>();
}
for (int v = 0; v < G.V(); v++) {
res[visited[v]].add(v);
}
return res;
}
public static void main(String[] args) {
Graph g = new Graph("g_4.txt");
CC cc = new CC(g);
System.out.println(cc.count());
ArrayList<Integer>[] ret = cc.components();
for (int ccid = 0; ccid < ret.length; ccid++) {
System.out.print(ccid + ": ");
for (Integer v : ret[ccid]) {
System.out.print(v + " ");
}
System.out.println();
}
}
}
2. 路径问题
单源最短路
import java.util.ArrayList;
import java.util.Collections;
public class SingleSourcePath {
private Graph G;
private int s; //source:从哪个源头开始
private boolean[] visited;
private int[] pre; //保存到达某个点的上个节点的编号
SingleSourcePath(Graph G, int s) {
this.G = G;
this.s = s;
visited = new boolean[G.V()];
pre = new int[G.V()];
for (int i = 0; i < pre.length; i++) {
pre[i] = -1;
}
//解决非连通图的遍历问题
// for (int v = 0; v < G.V(); v++) {
// if(!visited[v])
// dfs(v);
// }
dfs(s, s);
}
private void dfs(int v, int parent) {
visited[v] = true;
pre[v] = parent;
for (int w : G.adj(v)) {
if (!visited[w])
dfs(w, v);
}
}
//判断s到v是否有路径(联通)
public boolean isConnectedTo(int v) {
this.G.validateVertex(v);
return visited[v]; // return pre[v] != -1;
}
//保存源到某个节点路径
public Iterable<Integer> path(int v) {
ArrayList<Integer> res = new ArrayList<>();
if (!isConnectedTo(v)) return res;
int cur = v;
while (cur != this.s) {
res.add(cur);
cur = pre[cur];
}
res.add(this.s);
Collections.reverse(res);
return res;
}
public static void main(String[] args) {
Graph g = new Graph("g_3.txt");
SingleSourcePath singleSourcePath = new SingleSourcePath(g, 0);
System.out.println("0 -> 6" + singleSourcePath.path(6));
}
}
所有点对路径问题(All Pairs Vertices Path Problem):对图中每个节点都实现一遍“单源最短路径”
- 注:本系列参考玩转算法系列–图论精讲