# 图算法系列之深度优先搜索（二）

767

## 连通分量

#### 连通分量的API定义

``````public class DepthFirstCC {
public DepthFirstCC(Graph graph);

public boolean connected(int v, int w); //检查两个顶点是否连通

public int count(); //统计连通分量的总数

public int id(int v); //顶点v所在连通分量的标识
}
``````

#### 连通分量的API实现

``````public class DepthFirstCC {
private boolean marked[];
private int count;
private int[] ids;

public DepthFirstCC(Graph graph) {
this.marked = new boolean[graph.V()];
this.ids = new int[graph.V()];

for (int v = 0; v < graph.V(); v++) {
if (!this.marked[v]) {
dfs(graph, v);
count++;
}
}
}

private void dfs(Graph graph, int v) {
this.marked[v] = true;
this.ids[v] = count;
for (int w : graph.adj(v)) {
if (!this.marked[w]) {
dfs(graph, w);
}
}
}

public boolean connected(int v, int w) {
return id(v) == id(w);
}

public int count() {
return count;
}

public int id(int v) {
return ids[v];
}

}
``````

#### 单元测试

``````@Test
public void test() {
Graph graph = new Graph(10);

DepthFirstCC cc = new DepthFirstCC(graph);

System.out.println(cc.connected(0,5));
System.out.println(cc.connected(1,2));

System.out.println(cc.count());
}

``````

## 检查无向图中是否有环

1. 标记已经搜索过的每个顶点
2. 当遇到了一个已经被标记过的顶点，表示已经图中存在环；
3. 由于图是无向图，如果v-w相连，那么顶点v中的邻接表中有w，w邻接表中也会有v，但是他们没有构成环，所以需要排除掉该情况。
``````public class Cycle {
private boolean marked[];
private boolean hashCycle;

public Cycle(Graph graph) {
this.marked = new boolean[graph.V()];
for (int s = 0; s < graph.V(); s++) {
if (!this.marked[s]) {
dfs(graph, s, s);
}
}
}

private void dfs(Graph graph, int v, int pV) {
this.marked[v] = true;
for (int w : graph.adj(v)) {
if (!this.marked[w]) {
this.dfs(graph, w, v);
} else if (w != pV) {
this.hashCycle = true;
return;
}
}
}

public boolean hasCycle() {
return hashCycle;
}
}
``````

## 检查无向图是否是二分图

``````public class TwoColorGraph {
private boolean twoColor = true;
private boolean[] marked;
private boolean[] color;

public TwoColorGraph(Graph graph) {
this.marked = new boolean[graph.V()];
this.color = new boolean[graph.V()];

for (int v = 0; v < graph.V(); v++) {
if (!this.marked[v]) {
dfs(graph, v);
}
}
}

private void dfs(Graph graph, int v) {
this.marked[v] = true;
for (int w : graph.adj(v)) {
if (!this.marked[w]) {
this.color[w] = !this.color[v];
dfs(graph, w);
} else if (this.color[w] == this.color[v]) {
this.twoColor = false;
return;
}
}
}

public boolean isTwoColor() {
return twoColor;
}
}
``````