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):對圖中每個節點都實現一遍“單源最短路徑”
- 注:本系列參考玩轉算法系列–圖論精講