Graph Theory Algorithm (4): Depth-First Traversal DFS of Graphs

The content of this chapter is implemented in java, Github code warehouse: https://github.com/ZhekaiLi/Code/tree/main/Graph/src

Viewing the pictures in the article may require scientific Internet access!Because github is used to manage pictures, if there is a situation that cannot be loaded, please turn over the wall

[Reference] imooc Mr. Bobo: Fun Algorithm Series - Graph Theory Essentials for Interview and Promotion (Java Edition)

[Links to previous blogs]
Graph Theory Algorithms (1, 2): Classification of Graphs, Basic Concepts of Graphs (Undirected Graphs and Directed Graphs, Unweighted Graphs, Acyclic Graphs, Complete Graphs, Bipartite Graphs; Simple Graphs, Connected Graphs Components, spanning tree of graphs, subgraphs and parent graphs)
graph theory algorithm (3): basic representation of graphs (adjacency matrix, adjacency list, comparison of adjacency matrix and adjacency list)
graph theory algorithm (4): depth first of graphs Traversal DFS
Graph Theory Algorithm (5): Graph Breadth First Traversal BFS
Graph Theory Algorithm (6): LeetCode Graph Theory Algorithm Exercise (785. Judgment of Bipartite Graph, 695. Maximum Area of ​​Island, Floodfill Algorithm, Union Check)

4 Depth-first traversal of DFS for graphs

(About the front, middle, back, and layer order traversal of the tree, there is a blog that summarizes it very well: https://blog.csdn.net/zl6481033/article/details/81009388 )
Let's first look at the depth-first traversal of the tree (previously In-order traversal as an example)

preorder(root); // 从根结点开始遍历

preorder(TreeNode node)
    if(node != null)
        list.add(node.val);
        preorder(node.left);
        preorder(node.right);

Depth-first-order traversal of graphs : slightly different from trees, graph algorithms need to determine whether a node has been visited before recursion, and its time complexity is O ( V + E ) O(V+E)O ( V+E)

visited[0...V-1] = false;

// 使用 for 循环保证遍历每个点,使得算法可以应对非联通图
for(int v = 0; v < V; v++)
    if(!visited[v])
        dfs(v);

dfs(int v)
    visited[v] = true; // 标记为已访问
    list.add(v);
    for(int w: adj(v))
        if(!visited[w])
            dfs(w);

java implementation: GraphDFS.java

4.1 Ex: Find the connected component

That is, the solution contains several connected graphs

visited[0...V-1] = -1;
ccount = 0; // 联通分量

for(v = 0; v < V; v++)
    if(visited[v] == -1)
        dfs(v, ccount);
        ccount++;

dfs(v, ccid)
    visited[v] = ccid;
    list.add(v);
    for(int w: adj(v))
        if(visited[w] == -1)
            dfs(w, ccid);

java implementation: CC.java

Find whether two points are reachable : only need to judge as follows

visited[v] == visited[w];

4.2 Ex: Find the path between two points

(not necessarily the shortest)

// pre[i] = j 表示存在路径 j->i
// pre[i] = -1 表示尚未访问,代替 visited[i] = false
pre[0...V-1] = -1;
s = 0; // 自定义的起始点
t = 5; // 自定义的终止点

pre[s] = s; // 将源头的源头设为自己
dfs(s);

// 返回值表示是否达到了目标点 t
boolean dfs(int v)
    for(int w: adj(v))
        if(visited[w] == -1)
            pre[w] = v;
            if(w == t) return true;
            if(dfs(w)) return true;
    return false;

==java implementation: Path.java==

4.3 Ex: Ring Detection

java implementation: CycleDetection.java

4.4 Ex: Bipartite Graph Detection



The two graphs on the left and right that look completely different are actually the same, but the form on the left is obviously a bipartite graph, while the more common and random form on the right cannot be judged intuitively.

Use DFS for bipartite graph detection:

// -1: 未访问
// 0: 二分图的一侧
// 1: 二分图的另一侧
color[0...V-1] = -1;

color[0] = 0;
dfs(0);

// 返回值表示是否检测到了目标图不是二分图的证据
boolean dfs(int v)
    for(int w: adj(v))
        if(color[w] == -1)
            color[w] = 1 - color[v]
            if(dfs(w)) return true;
        else if(color[w] == color[v])
            return true
    return false;

java implementation: BipartitionDetection.java

Guess you like

Origin blog.csdn.net/weixin_43728138/article/details/118937700