Question writing diary 09 "Basics of Graph Theory"

Graph storage structure

For graph structures, there are two main common storage structures: adjacency lists and adjacency matrices:

 

The adjacency list is very intuitive. I  x store the neighbors of each node in a list, and then  x associate it with this list, so that  x all of its adjacent nodes can be found through a node.

The adjacency matrix is ​​a two-dimensional Boolean array, which we call arbitrarily  matrix. If the nodes  x and  y are connected, then  matrix[x][y] set it to  true(represented by the green square in the figure above  true). If you want to find  x the neighbors of a node, just scan around  matrix[x][..] .

So, why are there two ways of storing graphs? It must be because they each have their own pros and cons.

For adjacency lists, the advantage is that they take up less space.

You see there are so many empty positions in the adjacency matrix, which definitely requires more storage space.

However, the adjacency list cannot quickly determine whether two nodes are adjacent.

For example, if I want to determine  1 whether  a node 3 is adjacent to a node, I need to  check  whether it exists 1 in the corresponding neighbor list in  the adjacency table. 3But for the adjacency matrix, it is simple, just look at it  matrix[1][3] and you will know, and it is very efficient.

Therefore, which method to use to implement the graph depends on the specific situation.

Graph traversal template

In graph theory questions, the most common traversal method is DFS, which is depth-first traversal. Graphs are different from binary trees. Binary tree traversal does not produce duplication, but graph traversal does, so we need to use additional storage space to judge. Whether to repeatedly traverse this point, the specific traversal template for depth-first traversal is as follows:

// 记录被遍历过的节点
boolean[] visited;
// 记录从起点到当前节点的路径
boolean[] onPath;

/* 图遍历框架 */
void traverse(Graph graph, int s) {
    if (visited[s]) return;
    // 经过节点 s,标记为已遍历
    visited[s] = true;
    // 做选择:标记节点 s 在路径上
    onPath[s] = true;
    for (int neighbor : graph.neighbors(s)) {
        traverse(graph, neighbor);
    }
    // 撤销选择:节点 s 离开路径
    onPath[s] = false;
}

topic

Question description

Given a directed acyclic graph with n nodes, represented by a two-dimensional array graph, find all paths from 0 to n-1 and output them (order is not required).

The units in the i-th array of graph all represent the next nodes that can be reached by node i in the directed graph (Translator's Note: The directed graph is directional, that is, if a→b is specified, you cannot go from b →a), if it is empty, there is no next node.

Example 1:

Input: graph = [[1,2],[3],[3],[]]
Output: [[0,1,3],[0,2,3]]
Explanation: There are two paths 0 -> 1 -> 3 and 0 -> 2 -> 3
Example 2:

Input: graph = [[4,3,1],[3,2,4],[3],[4],[]]
Output: [[0,4],[0,3,4],[ 0,1,3,4],[0,1,2,3,4],[0,1,4]]
Example 3:

Input: graph = [[1],[]]
Output: [[0,1]]
Example 4:

Input: graph = [[1,2,3],[2],[3],[]]
Output: [[0,1,2,3],[0,2,3],[0,3] ]
Example 5:

Input: graph = [[1,3],[2],[3],[]]
Output: [[0,1,2,3],[0,3]]

 

hint:

n == graph.length
2 <= n <= 15
0 <= graph[i][j] < n
graph[i][j] != i 

guarantees that the input is a directed acyclic graph (GAD)

Problem-solving ideas

From the meaning of the question, we can get: graph[i] represents the element directly connected to i. In other words, graph actually maintains an adjacency list. The question clearly states that there is no cycle (nodes will not point to each other), so We do not need to set visit[][] to determine whether the node has been visited. We only need to loop through the last shift of dfs until we reach the last node.

Example code

class Solution {
    int size;
        LinkedList<List<Integer>>res=new LinkedList<>();
        LinkedList<Integer>path=new LinkedList<>();
    public List<List<Integer>> allPathsSourceTarget(int[][] graph) {
        size=graph.length;
        path=new LinkedList<>();
        dfs(graph,0);
        return res;

    }
    public void dfs(int[][]graph,int index){
        //添加
        path.add(index);
        //定义递归出口
        if(index==size-1){
            //添加最后一个元素
            res.add(new LinkedList(path));
        }
         //循环
            for(int i=0;i<graph[index].length;++i){
                dfs(graph,graph[index][i]);
            }
            //删除
            path.removeLast();
    }
}

Guess you like

Origin blog.csdn.net/m0_65431718/article/details/131851055