Algoritmo de teoría de grafos (4): DFS transversal primero en profundidad de grafos

El contenido de este capítulo está implementado en Java, almacén de código de Github: https://github.com/ZhekaiLi/Code/tree/main/Graph/src

¡Ver las imágenes en el artículo puede requerir acceso científico a Internet!Debido a que github se usa para administrar imágenes, si hay una situación que no se puede cargar, voltee la pared

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

[Enlaces a blogs anteriores]
Algoritmos de teoría de grafos (1, 2): clasificación de grafos, conceptos básicos de grafos (gráficos no dirigidos y gráficos dirigidos, gráficos no ponderados, gráficos acíclicos, gráficos completos, gráficos bipartitos; gráficos simples, componentes de gráficos conectados, expansión árbol de gráficos, subgráficos y gráficos principales)
algoritmo de teoría de gráficos (3): representación básica de gráficos (matriz de adyacencia, lista de adyacencia, comparación de matriz de adyacencia y lista de adyacencia)
algoritmo de teoría de gráficos (4): primera profundidad de gráficos
Teoría de gráficos DFS transversal Algoritmo (5): Amplitud de gráfico Primer recorrido BFS
Algoritmo de teoría de gráficos (6): LeetCode Ejercicio de algoritmo de teoría de gráficos (785. Juicio de gráfico bipartito, 695. Área máxima de isla, Algoritmo de relleno de inundación, Verificación de unión)

4 Recorrido primero en profundidad de DFS para gráficos

(Sobre el recorrido del árbol por delante, por en medio, por detrás y por capas, hay un blog que lo resume muy bien: https://blog.csdn.net/zl6481033/article/details/81009388 )
Veamos primero el Recorrido primero en profundidad del árbol (anteriormente Recorrido en orden como ejemplo)

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

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

Recorrido de grafos de primer orden en profundidad : ligeramente diferente de los árboles, los algoritmos de grafos necesitan determinar si un nodo ha sido visitado antes de recurrir, y su complejidad de tiempo es O ( V + E ) O(V+E)O ( V+mi )

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);

implementación java: GraphDFS.java

4.1 Ej: encontrar el componente conectado

Es decir, la solución contiene varios gráficos conectados.

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);

implementación java: CC.java

Encuentre si dos puntos son alcanzables : solo necesita juzgar de la siguiente manera

visited[v] == visited[w];

4.2 Ej: encontrar el camino entre dos puntos

(no necesariamente el más corto)

// 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;

==implementación de Java: Path.java==

4.3 Ej.: Detección de timbre

implementación java: CycleDetection.java

4.4 Ej.: Detección de gráfico bipartito



Los dos gráficos de la izquierda y la derecha que parecen completamente diferentes son en realidad iguales, pero la forma de la izquierda es obviamente un gráfico bipartito, mientras que la forma más ordinaria y aleatoria de la derecha no se puede juzgar intuitivamente.

Use DFS para la detección de gráficos bipartitos:

// -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;

implementación de java: BipartitionDetection.java

Supongo que te gusta

Origin blog.csdn.net/weixin_43728138/article/details/118937700
Recomendado
Clasificación