Fundamentos

Componentes conexas, puentes y puntos de articulación

Que un grafo se mantenga unido, y con qué firmeza, depende de unas pocas ideas: componentes, puentes y vértices de corte. Esta guía define cada una, demuestra cómo se relacionan, las encuentra todas con una sola búsqueda en profundidad en código Python probado, muestra dos errores que pasan desapercibidos en pruebas sencillas y avanza hasta los bloques, el árbol de bloques y vértices de corte y los números que miden la conectividad.

21 Min de lectura Actualizado: Octubre 2026 Nivel Principiante
Mohammed Islam Hadjoudj
Mohammed Islam Hadjoudj
Expert Operations Research Engineer

1. Qué significa «conexo»

Un grafo es conexo cuando hay un camino entre cada par de sus vértices. Puedes empezar en cualquier parte y, siguiendo aristas, llegar a todas partes. Cuando eso falla, el grafo se descompone en piezas llamadas componentes conexas: los mayores subgrafos conexos que contiene, sin ninguna arista entre dos piezas distintas.

La forma más clara de ver las componentes es a través de la relación «u puede alcanzar a v». Es reflexiva (cada vértice se alcanza a sí mismo por el camino vacío), simétrica (en un grafo no dirigido un camino puede recorrerse al revés) y transitiva (dos caminos pueden unirse uno tras otro). Una relación con esas tres propiedades es una relación de equivalencia, y toda relación de equivalencia divide su conjunto en clases disjuntas. Las clases de la alcanzabilidad son exactamente las componentes. Por eso cada vértice pertenece a exactamente una componente, y por eso un vértice aislado, sin ninguna arista, es una componente por sí solo.

Un solo grafo recorre todo el artículo. Tiene doce vértices y trece aristas, y está construido para que cada idea de abajo tenga un ejemplo concreto y, cuando importa, un contraejemplo concreto:

V = {A, B, C, D, E, F, G, H, I, J, K, L}
E = {AB, BC, CA, CD, DE, EC, EF, FG, GH, HI, IF, IJ, KL}        13 aristas

componente 1 = {A, B, C, D, E, F, G, H, I, J}    12 aristas
componente 2 = {K, L}                              1 arista
El grafo de ejemplo con sus dos componentes sombreadas. La componente 1, en azul, contiene de A a J: dos triángulos A, B, C y C, D, E que comparten el vértice C, una arista de E a F, un cuadrado F, G, H, I y un vértice colgante J unido a I. La componente 2, en violeta, es la única arista de K a L. Las etiquetas indican 10 vértices y 12 aristas para la componente 1 y 2 vértices y 1 arista para la componente 2.
El ejemplo tiene dos componentes. Dentro de cada una, cada vértice alcanza a todos los demás; entre ellas no hay ningún camino.

El vocabulario viene de la guía de vértices y aristas, y todo lo que sigue trata de grafos no dirigidos hasta la sección 11, donde la dirección cambia la historia.

2. Encontrar las componentes

Como las componentes son clases de alcanzabilidad, cualquier búsqueda en el grafo las encuentra. Lanza una búsqueda en anchura o en profundidad desde algún vértice; todo lo que alcanza es la componente de ese vértice. Luego vuelve a empezar desde cualquier vértice aún no alcanzado, y repite hasta que no quede ninguno. Cada nuevo comienzo es una componente más.

from collections import deque

def connected_components(graph):
    """Etiqueta cada vértice de un grafo no dirigido con el índice de su componente."""
    label, components = {}, []
    for start in graph:                      # los vértices aislados forman su propia componente
        if start in label:
            continue
        label[start] = len(components)
        members, queue = [start], deque([start])
        while queue:
            u = queue.popleft()
            for v in graph[u]:
                if v not in label:
                    label[v] = len(components)
                    members.append(v)
                    queue.append(v)
        components.append(sorted(members))
    return components, label

edges = ['AB', 'BC', 'CA', 'CD', 'DE', 'EC', 'EF', 'FG', 'GH', 'HI', 'IF', 'IJ', 'KL']
graph = {v: [] for v in 'ABCDEFGHIJKL'}
for u, v in edges:
    graph[u].append(v)
    graph[v].append(u)

components, label = connected_components(graph)
print(len(components), components)
# 2 [['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J'], ['K', 'L']]
print(label['H'] == label['A'], label['K'] == label['A'])
# True False

Cada vértice se etiqueta una vez y cada arista se examina dos veces, una desde cada extremo, así que todo el trabajo lleva un tiempo O(V + E) en total. El bucle exterior sobre todos los vértices es la línea importante. Una sola búsqueda responde a «qué puedo alcanzar desde aquí», no a «cuántas piezas hay», y olvidar el bucle es una forma habitual de contar 1 componente en un grafo que tiene varias.

Vale la pena conocer dos alternativas. Si las aristas llegan de una en una y solo las añades, una estructura union-find mantiene las componentes al día en un tiempo amortizado casi constante por arista: cada arista fusiona las clases de sus dos extremos, y dos vértices están en la misma componente exactamente cuando tienen la misma raíz. La idea se remonta al algoritmo de equivalencia de Galler y Fischer de 1964. Y en el procesamiento de imágenes, donde el «grafo» es una cuadrícula de píxeles, el mismo problema se llama etiquetado de componentes conexas. Rosenfeld y Pfaltz describieron un barrido secuencial para ello en 1966. Que cuenten los vecinos diagonales, lo que se llama 8-conectividad, o solo los cuatro vecinos rectos, lo que se llama 4-conectividad, cambia qué formas son una sola región y cuáles son dos.

Incluso hay una respuesta algebraica. La matriz laplaciana de un grafo, con los grados en la diagonal y −1 por cada arista, tiene el valor propio 0 con multiplicidad exactamente igual al número de componentes. En el ejemplo esa multiplicidad es 2. La relación entre valores propios y estructura se desarrolla en la teoría espectral de grafos.

3. Lo que dice el número de componentes

Llama n al número de vértices, m al número de aristas y k al número de componentes. Unos pocos hechos relacionan los tres, y sirven como comprobaciones de cordura para cualquier programa que cuente componentes.

Un grafo con n vértices y k componentes tiene al menos n − k aristas, con igualdad exactamente cuando es un bosque.

La demostración es un argumento de conteo. Parte de n vértices aislados, que son n componentes, y añade las aristas una a una. Cada arista o bien une dos componentes distintas, lo que reduce la cuenta en uno, o bien cae dentro de una componente y no cambia nada. Para bajar a k componentes necesitas al menos n − k aristas del primer tipo, y tienes exactamente esas cuando ninguna arista se desperdició en cerrar un ciclo. Un bosque es precisamente un grafo sin ciclos, y un árbol es un bosque conexo, por eso un árbol con n vértices tiene n − 1 aristas, como la guía de árboles en teoría de grafos demuestra de varias otras formas. El ejemplo cumple 13 ≥ 12 − 2 = 10, con tres aristas de sobra, una por cada uno de sus tres ciclos.

La otra dirección también tiene un techo. Un grafo simple con k componentes tiene como mucho C(n − k + 1, 2) aristas, cota que se alcanza poniendo n − k + 1 vértices en un grafo completo y dejando aislados los otros k − 1. Un corolario es una prueba rápida de conectividad: un grafo simple con más de C(n − 1, 2) aristas no puede tener dos componentes, así que debe ser conexo.

Otro hecho es un ejercicio clásico con una demostración de dos líneas: un grafo o su complemento siempre es conexo. Si G es disconexo, toma dos vértices cualesquiera. Si están en componentes distintas de G, son adyacentes en el complemento. Si están en la misma componente, elige cualquier vértice de otra componente; es adyacente a ambos en el complemento. En cualquier caso quedan unidos por un camino de longitud como mucho dos. Estos tres hechos se comprobaron por fuerza bruta sobre todos los grafos simples de hasta seis vértices.

4. Puentes: las aristas que no puedes perder

La conectividad no trata solo de si un grafo se mantiene unido, sino de con qué firmeza. Un puente, también llamado arista de corte, es una arista cuya eliminación aumenta el número de componentes. Borrarla divide su componente en exactamente dos piezas, nunca más, porque quitar una arista solo puede separar entre sí a sus dos extremos.

Una arista es un puente si y solo si no está en ningún ciclo.

Si una arista uv está en un ciclo, el resto del ciclo es una segunda ruta de u a v, así que quitar la arista no desconecta nada. A la inversa, si al quitar uv quedan u y v conectados, el camino restante de v de vuelta a u junto con uv forma un ciclo. Así que los puentes son exactamente las aristas sin ruta alternativa. Se siguen dos consecuencias inmediatas: en un árbol cada arista es un puente, y una arista entre dos vértices unidos por una segunda arista paralela nunca es un puente.

El ejemplo tiene tres puentes: E–F, I–J y K–L. Quitar cualquiera de ellos eleva el número de componentes de 2 a 3. Todas las demás aristas están en uno de los tres ciclos: los dos triángulos y el cuadrado.

El grafo de ejemplo con sus tres puentes, E a F, I a J y K a L, dibujados como gruesas líneas rojas y sus cuatro vértices de corte, C, E, F e I, rellenos de naranja. Una nota bajo C dice que C es un vértice de corte pero que ningún puente lo toca. Una nota junto a K y L dice que K a L es un puente sin vértice de corte en ninguno de sus extremos.
Puentes en rojo, vértices de corte en naranja. Las dos notas son los contraejemplos que mantienen separadas las dos ideas.

5. Puntos de articulación: los vértices que no puedes perder

Un punto de articulación, también llamado vértice de corte, es un vértice cuya eliminación, junto con sus aristas, aumenta el número de componentes. De forma equivalente, v es un vértice de corte cuando hay otros dos vértices u y w en su componente tales que todo camino de u a w pasa por v.

A diferencia de un puente, un vértice de corte puede dividir su componente en muchas piezas a la vez. Quita el centro de una estrella con cinco hojas y quedan cinco componentes. En el ejemplo, al quitar C quedan tres componentes: {A, B}, todo lo que va de D a J, y {K, L}, que ya estaba separada.

Los puentes y los vértices de corte están relacionados, y la relación es una trampa que conviene enunciar con cuidado:

Así que el ejemplo tiene cuatro vértices de corte, C, E, F e I, y las dos ideas son realmente distintas: los fallos de vértices y los fallos de enlaces revelan puntos débiles diferentes en la misma red.

El algoritmo obvio borra cada arista, o cada vértice, por turno y vuelve a contar las componentes. Eso cuesta una búsqueda completa por candidato, O(E(V + E)) para los puentes. En 1972 y 1973, Tarjan, y Hopcroft y Tarjan, demostraron que basta con una sola búsqueda en profundidad, con un coste de O(V + E) en total. El método se basa en dos números por vértice.

En una búsqueda en profundidad no dirigida, toda arista que no es de árbol es una arista de retroceso: une un vértice con uno de sus antepasados. Una arista de retroceso es una vía de escape, una forma de salir de un subárbol sin usar la arista de árbol que tiene encima. Ambas pruebas preguntan si existe tal vía. Para una arista de árbol del padre u al hijo v:

puente             u–v es un puente                si  low[v] > disc[u]    nada bajo v llega a u ni más arriba
vértice de corte   u es un vértice de corte        si  low[v] ≥ disc[u]    nada bajo v llega por encima de u
raíz               la raíz es un vértice de corte  si tiene 2 o más hijos en el árbol DFS

La raíz necesita su propia regla porque no hay nada por encima de ella: separa el grafo exactamente cuando la búsqueda tuvo que salir de ella dos veces, lo que significa que sus subárboles no tienen ninguna arista entre sí. Este es el método completo, escrito de forma iterativa para que un camino largo no desborde la pila de llamadas de Python:

def bridges_and_cut_vertices(vertices, edges):
    """Método low-link de Tarjan, iterativo. Las aristas son pares (u, v); se permiten aristas paralelas."""
    adj = {v: [] for v in vertices}
    for i, (u, v) in enumerate(edges):       # guarda los ids de las aristas, no solo los vecinos
        adj[u].append((v, i))
        adj[v].append((u, i))
    disc, low, bridges, cuts, clock = {}, {}, [], set(), 0
    for root in vertices:
        if root in disc:
            continue
        disc[root] = low[root] = clock; clock += 1
        children = 0
        stack = [(root, -1, iter(adj[root]))]  # (vértice, id de la arista por la que llegamos, vecinos)
        while stack:
            u, in_edge, it = stack[-1]
            for v, i in it:
                if i == in_edge:             # salta solo esa arista, no todas las que vuelven al padre
                    continue
                if v in disc:                # arista de retroceso: una vía de escape hacia arriba en el árbol
                    low[u] = min(low[u], disc[v])
                else:                        # arista de árbol: descender
                    disc[v] = low[v] = clock; clock += 1
                    stack.append((v, i, iter(adj[v])))
                    break
            else:                            # u ha terminado: informa a su padre p
                stack.pop()
                if stack:
                    p = stack[-1][0]
                    low[p] = min(low[p], low[u])
                    if low[u] > disc[p]:
                        bridges.append(edges[in_edge])
                    if low[u] >= disc[p] and p != root:
                        cuts.add(p)
                    if p == root:
                        children += 1
        if children >= 2:                    # la raíz es vértice de corte solo con 2+ hijos DFS
            cuts.add(root)
    return bridges, sorted(cuts), disc, low

edges = ['AB', 'BC', 'CA', 'CD', 'DE', 'EC', 'EF', 'FG', 'GH', 'HI', 'IF', 'IJ', 'KL']
bridges, cuts, disc, low = bridges_and_cut_vertices('ABCDEFGHIJKL', edges)
print(bridges)
# ['IJ', 'EF', 'KL']
print(cuts)
# ['C', 'E', 'F', 'I']

print(bridges_and_cut_vertices('xy', ['xy', 'xy'])[0])   # una arista doble no es un puente
# []

En el ejemplo, la búsqueda desde A recorre por casualidad un camino recto, A, B, C, …, J, y las tres aristas que no son de árbol C–A, E–C y I–F se convierten en aristas de retroceso. La figura muestra los números resultantes.

El árbol de la búsqueda en profundidad de la componente 1 dibujado como un camino de A a J con los valores disc y low bajo cada vértice: A, B y C tienen low 0, D y E tienen low 2, F, G, H e I tienen low 5, J tiene low 9. Aristas de retroceso discontinuas forman arcos de C a A, de E a C y de I a F. Las aristas de árbol E a F e I a J son puentes rojos y C, E, F e I son vértices de corte naranjas. Un recuadro detalla dos pruebas: low de F igual a 5, mayor que disc de E igual a 4, así que E a F es un puente; low de D igual a 2, al menos disc de C igual a 2, así que C es un vértice de corte.
Todos los puentes y vértices de corte de la componente 1 salen de esta única tabla de números.

Leer la tabla con las reglas da todas las respuestas. low[F] = 5 es mayor que disc[E] = 4, así que nada por debajo de F vuelve a subir hasta E, y E–F es un puente; I–J es un puente por la misma razón, con 9 > 8. low[D] = 2 es igual a disc[C] = 2: el subárbol bajo C puede volver a subir hasta el propio C, pero no más arriba, así que C es un vértice de corte aunque ningún puente lo toque. Y A, la raíz, tiene un solo hijo, así que no lo es.

Mira cómo se asientan los valores low-link

Construye los dos triángulos que comparten C, ejecuta la búsqueda de puntos de articulación y comprueba por qué aparece C aunque cada arista a su alrededor esté en un ciclo.

Abrir el buscador de puntos de articulación

7. Dos errores que superan las pruebas sencillas

El código low-link es corto, y dos de sus errores clásicos dan respuestas correctas en la mayoría de los ejemplos pequeños. Ambos se compararon con la fuerza bruta: la versión de arriba coincide con «bórralo y vuelve a contar» en 5.000 multigrafos aleatorios.

Saltar el vértice padre en lugar de la arista padre. Cuando la búsqueda examina los vecinos de v, no debe tratar la arista de árbol por la que llegó como una arista de retroceso, o cada vértice podría escapar a través de su propio padre. Muchas implementaciones saltan «el vecino igual a mi padre». Eso funciona en un grafo simple, pero con dos aristas paralelas entre x y y salta las dos, y la arista doble aparece como puente aunque borrar una copia no desconecte nada. Saltar esa única arista por su identidad, como hace el código con in_edge, es correcto para los multigrafos también.

Usar low[w] en lugar de disc[w] en una arista de retroceso. La actualización a lo largo de una arista de retroceso hacia w debe usar disc[w]. Escribir low[w] permite que la vía de escape continúe más allá de w por aristas que pertenecen a otro bloque. Para los puentes esto resulta inofensivo: en 20.000 grafos aleatorios la variante nunca falló un puente. Para los vértices de corte no lo es: la misma prueba lo detectó en 35 de los grafos, y el fallo más pequeño que encontró esa búsqueda es el par de triángulos que comparten C. Con low[w], la arista de retroceso E–C importa low[C] = 0, así que low[D] pasa a valer 0, la prueba en C falla y el vértice de corte desaparece de la salida.

8. Bloques y el árbol de bloques y vértices de corte

Los vértices de corte dividen un grafo conexo en piezas naturales. Un bloque es un subgrafo conexo maximal sin vértices de corte propios: o bien una pieza 2-conexa (que sigue siendo conexa tras borrar cualquier vértice), o bien un solo puente, o bien un vértice aislado. Cada arista pertenece a exactamente un bloque, y dos bloques comparten como mucho un vértice, que entonces es un vértice de corte. Los bloques también se llaman componentes biconexas, y el algoritmo de Hopcroft y Tarjan de 1973 los encuentra en esa misma búsqueda, manteniendo una pila de aristas y sacando un bloque cada vez que se cumple la prueba del vértice de corte.

El ejemplo tiene seis bloques: los triángulos {A, B, C} y {C, D, E}, el cuadrado {F, G, H, I} y los tres puentes {E, F}, {I, J} y {K, L}.

Izquierda: el grafo de ejemplo con sus aristas coloreadas por bloque, los triángulos A, B, C en azul y C, D, E en verde azulado, el cuadrado F, G, H, I en violeta y los tres puentes en rojo, con los vértices de corte C, E, F e I en naranja. Derecha: el árbol de bloques y vértices de corte de la componente 1, una cadena de nodos de bloque A B C, C D E, E F, F G H I e I J que se alternan con los nodos de vértice de corte C, E, F e I, con la etiqueta 9 nodos y 8 aristas.
Los bloques del ejemplo y el árbol de bloques y vértices de corte de su primera componente. Contraer cada bloque en un solo nodo siempre deja un árbol.

El árbol de bloques y vértices de corte, introducido por Harary y Prins en 1966, tiene un nodo por cada bloque y otro por cada vértice de corte, con una arista siempre que el vértice de corte está en el bloque. Para un grafo conexo siempre es un árbol. Para la componente 1 tiene 5 nodos de bloque y 4 nodos de vértice de corte: 9 nodos unidos por 8 aristas. El árbol es el esqueleto grueso del grafo: responde a «qué fallos separan qué partes» sin mirar dentro de ningún bloque.

Los puentes dan una descomposición paralela. Borra todos los puentes, y lo que queda se divide en componentes 2-conexas por aristas, piezas que sobreviven a la pérdida de cualquier arista. El ejemplo tiene cinco: {A, B, C, D, E}, {F, G, H, I} y los vértices sueltos {J}, {K} y {L}. Observa que la primera es una sola componente 2-conexa por aristas pero dos bloques. La pajarita sobrevive al fallo de cualquier arista, pero no al fallo de C.

Dos teoremas clásicos explican lo que aporta realmente «no tener vértices de corte». Whitney demostró en 1932 que un grafo con al menos tres vértices es 2-conexo exactamente cuando cada par de vértices está unido por dos caminos sin vértices interiores en común, lo que equivale a decir que cada par de vértices está en un ciclo común. Y Robbins demostró en 1939 que a las aristas de un grafo conexo se les pueden dar direcciones de modo que cada vértice alcance a todos los demás exactamente cuando el grafo no tiene puentes, el teorema central de la guía de grafos dirigidos y no dirigidos.

9. Medir cuán conexo es un grafo

Los puentes y los vértices de corte son el primer peldaño de una escalera. La conectividad por vértices κ(G) es el menor número de vértices cuya eliminación desconecta el grafo o deja un solo vértice. La conectividad por aristas λ(G) es el menor número de aristas cuya eliminación lo desconecta. Un grafo conexo con al menos tres vértices tiene un vértice de corte exactamente cuando κ = 1, y un grafo conexo con al menos dos vértices tiene un puente exactamente cuando λ = 1. La desigualdad de Whitney de 1932 relaciona ambas con el grado mínimo δ(G):

κ(G)  ≤  λ(G)  ≤  δ(G)

dos triángulos que comparten C   κ = 1   λ = 2   δ = 2      un vértice de corte, pero ningún puente
componente 1 del ejemplo         κ = 1   λ = 1   δ = 1      J cuelga de una sola arista
cualquier ciclo                  κ = 2   λ = 2   δ = 2

La desigualdad de la derecha es fácil: borrar las aristas de un vértice de grado mínimo lo aísla. La de la izquierda dice que los fallos de vértices son siempre al menos tan peligrosos como los fallos de aristas, y la pajarita muestra que la diferencia puede ser real.

El teorema de Menger de 1927 convierte estos mínimos en máximos. El menor número de aristas cuya eliminación separa dos vértices u y v es igual al mayor número de caminos de u a v que no comparten ninguna arista. La versión para vértices es el mismo enunciado con caminos internamente disjuntos, y requiere que u y v no sean adyacentes, ya que ningún conjunto de otros vértices separa a dos vecinos. El teorema de Menger es un caso particular de flujo máximo igual a corte mínimo, que es también como se calcula la conectividad en la práctica.

10. Dónde importa esto

Las componentes, los puentes y los vértices de corte son el vocabulario del análisis de fallos. Siempre que un sistema pueda modelarse como cosas y enlaces, estos conceptos nombran sus puntos débiles.

ÁmbitoLas componentes significanUn puente o vértice de corte significa
Redes informáticasGrupos de máquinas que pueden comunicarse entre síUn único enlace o router cuyo fallo divide la red
Carreteras y ferrocarrilRegiones accesibles entre síUn único puente, túnel o cruce sin desvío
Redes eléctricasIslas que pueden repartirse la cargaUna línea o subestación que divide la red si se dispara
Redes socialesComunidades sin vínculos entre ellasUna persona que es el único vínculo entre dos grupos
ImágenesObjetos separados en una imagenUn cuello estrecho donde un solo píxel mantiene unida una forma

Las componentes también explican uno de los resultados más famosos sobre grafos aleatorios. Erdős y Rényi demostraron en 1960 que si añades aristas aleatorias a n vértices aislados, las componentes siguen siendo pequeñas hasta que el grado medio supera 1, y entonces, de forma bastante repentina, aparece una única componente gigante que contiene una fracción constante de todos los vértices. Esa transición de fase, tratada en la historia de la teoría de grafos, es la razón por la que las grandes redes reales casi siempre tienen una componente dominante rodeada de unas cuantas pequeñas dispersas.

Cuando el grafo cambia sin parar, la conectividad se convierte en un problema de estructuras de datos. Las inserciones por sí solas son fáciles con union-find. Las eliminaciones son mucho más difíciles, porque quitar una arista puede dividir o no una componente y averiguarlo parece requerir una búsqueda. Holm, de Lichtenberg y Thorup demostraron en 2001 que la conectividad, la 2-conectividad por aristas y la biconectividad pueden mantenerse bajo inserciones y eliminaciones en un tiempo amortizado polilogarítmico por actualización.

11. Grafos dirigidos: conectividad débil y fuerte

En un grafo dirigido, «u puede alcanzar a v» ya no es una relación simétrica, así que no es de equivalencia, y «la componente de v» exige elegir. Hay dos opciones estándar.

Ejecutar el código de componentes no dirigido sobre una lista de adyacencia dirigida no da ninguna de las dos respuestas. Solo sigue las aristas hacia delante, así que las «componentes» que devuelve dependen de dónde empezó cada búsqueda. O simetrizas primero las listas para obtener las componentes débiles, o usas un algoritmo de componentes fuertes.

12. Errores comunes

ErrorPor qué está malSolución
Lanzar una búsqueda y declarar el grafo conexoUna búsqueda solo encuentra la componente de su vértice inicialRecorre todos los vértices y cuenta cuántas búsquedas inicias
Olvidar los vértices aisladosUn vértice sin aristas es una componente por sí solo, y una entrada en forma de lista de aristas puede no mencionarloConstruye el conjunto de vértices por separado de las aristas
«Un vértice de corte siempre está en un puente»C en la pajarita es un vértice de corte y cada arista en él está en un triánguloComprueba vértices y aristas por separado
Saltar el vértice padre en el código low-linkEntonces una arista doble aparece como puenteSalta la arista de entrada por su identidad
Usar low[w] en una arista de retrocesoInofensivo para los puentes, pero se pierde vértices de corte como CUsa disc[w] para las aristas de retroceso y low[v] solo para los hijos en el árbol
Aplicar a la raíz la regla de los demás vérticesLa raíz siempre cumple low[v] ≥ disc[root]Haz de la raíz un vértice de corte solo si tiene dos o más hijos DFS
Recursión sobre un camino largo en PythonEl límite de recursión por defecto de 1.000 se alcanza mucho antes de agotar la memoriaUsa una pila explícita, como en el código de arriba
Usar código no dirigido en un grafo dirigidoEl resultado depende del orden de las búsquedasDecide primero entre componentes débiles y fuertes

13. Glosario

TérminoSignificado
Grafo conexoUn grafo con un camino entre cada par de vértices
Componente conexaUn subgrafo conexo maximal; una clase de la relación de alcanzabilidad
Puente, arista de corteUna arista cuya eliminación aumenta el número de componentes; una arista que no está en ningún ciclo
Punto de articulación, vértice de corteUn vértice cuya eliminación aumenta el número de componentes
Arista de retrocesoUna arista que no es de árbol en una búsqueda en profundidad y que une un vértice con un antepasado
Valor low-linkEl menor tiempo de descubrimiento alcanzable desde un subárbol usando como mucho una arista de retroceso
Bloque, componente biconexaUn subgrafo conexo maximal sin vértices de corte propios
Árbol de bloques y vértices de corteEl árbol con un nodo por bloque y por vértice de corte
Componente 2-conexa por aristasUna pieza que queda tras borrar todos los puentes
Conectividad por vértices κEl menor número de vértices cuya eliminación desconecta el grafo
Conectividad por aristas λEl menor número de aristas cuya eliminación desconecta el grafo
Componente giganteUna componente que contiene una fracción constante de todos los vértices

14. Preguntas frecuentes

¿Qué es una componente conexa de un grafo?

Una componente conexa es un conjunto maximal de vértices en el que cada vértice puede alcanzar a todos los demás por un camino, junto con las aristas entre ellos. Las componentes son las clases de la relación de alcanzabilidad, así que cada vértice pertenece a exactamente una, y un vértice aislado es una componente por sí solo. Un grafo es conexo exactamente cuando tiene una sola componente.

¿Cómo se encuentran las componentes conexas de un grafo?

Lanza una búsqueda en anchura o en profundidad desde cualquier vértice; todo lo que alcanza es una componente. Luego lanza una nueva búsqueda desde cualquier vértice aún no alcanzado, y repite hasta que todos los vértices estén etiquetados. El número de búsquedas iniciadas es el número de componentes, y todo el procedimiento tarda un tiempo O(V + E). Si las aristas solo se añaden, una estructura union-find mantiene las componentes al día.

¿Qué es un puente en un grafo?

Un puente, o arista de corte, es una arista cuya eliminación aumenta el número de componentes conexas. Una arista es un puente exactamente cuando no está en ningún ciclo, así que cada arista de un árbol es un puente y una arista con una copia paralela nunca lo es. Borrar un puente divide su componente en exactamente dos piezas.

¿Qué es un punto de articulación?

Un punto de articulación, o vértice de corte, es un vértice cuya eliminación, junto con sus aristas, aumenta el número de componentes conexas. A diferencia de un puente, puede dividir una componente en muchas piezas: quitar el centro de una estrella con cinco hojas deja cinco componentes. Un vértice de corte no necesita tocar ningún puente, como muestran dos triángulos que comparten un vértice.

¿Cómo encuentra el algoritmo de Tarjan los puentes y los puntos de articulación?

Ejecuta una búsqueda en profundidad y registra dos números por vértice: disc, el orden en que el vértice se alcanzó por primera vez, y low, el menor disc alcanzable desde su subárbol usando como mucho una arista de retroceso. Una arista de árbol de u a un hijo v es un puente cuando low[v] > disc[u]. Un u que no es la raíz es un vértice de corte cuando algún hijo v tiene low[v] ≥ disc[u], y la raíz es un vértice de corte cuando tiene dos o más hijos en el árbol de búsqueda. Todo se ejecuta en tiempo O(V + E).

¿Cuál es la diferencia entre un puente y un punto de articulación?

Un puente es una arista y un punto de articulación es un vértice; cada uno es un punto único de fallo de un tipo distinto. A menudo aparecen juntos, ya que un extremo de un puente es un vértice de corte salvo que tenga grado 1, pero ninguno implica el otro. Una arista suelta entre dos hojas es un puente sin vértice de corte, y el vértice compartido por dos triángulos es un vértice de corte sin puente.

15. Referencias

Las definiciones, teoremas y atribuciones anteriores proceden de estas fuentes, ordenadas cronológicamente.

  1. Menger, K. (1927). "Zur allgemeinen Kurventheorie." Fundamenta Mathematicae 10, 96 a 115. Caminos disjuntos y conjuntos separadores.
  2. Whitney, H. (1932). "Congruent Graphs and the Connectivity of Graphs." American Journal of Mathematics 54(1), 150 a 168.
  3. Whitney, H. (1932). "Non-separable and Planar Graphs." Transactions of the American Mathematical Society 34(2), 339 a 362. Junto con el artículo anterior, la desigualdad entre la conectividad por vértices, la conectividad por aristas y el grado mínimo, y la caracterización de los grafos 2-conexos mediante caminos disjuntos.
  4. Robbins, H. E. (1939). "A Theorem on Graphs, with an Application to a Problem of Traffic Control." American Mathematical Monthly 46(5), 281 a 283.
  5. Erdős, P. y Rényi, A. (1960). "On the Evolution of Random Graphs." Publications of the Mathematical Institute of the Hungarian Academy of Sciences 5, 17 a 61. La componente gigante.
  6. Galler, B. A. y Fischer, M. J. (1964). "An Improved Equivalence Algorithm." Communications of the ACM 7(5), 301 a 303. La idea de union-find para fusionar clases.
  7. Harary, F. y Prins, G. (1966). "The Block-Cutpoint-Tree of a Graph." Publicationes Mathematicae Debrecen 13, 103 a 107.
  8. Rosenfeld, A. y Pfaltz, J. L. (1966). "Sequential Operations in Digital Picture Processing." Journal of the ACM 13(4), 471 a 494. Etiquetado de componentes conexas en imágenes.
  9. Tarjan, R. E. (1972). "Depth-First Search and Linear Graph Algorithms." SIAM Journal on Computing 1(2), 146 a 160.
  10. Hopcroft, J. E. y Tarjan, R. E. (1973). "Algorithm 447: Efficient Algorithms for Graph Manipulation." Communications of the ACM 16(6), 372 a 378. Componentes biconexas y vértices de corte en tiempo lineal.
  11. Tarjan, R. E. (1974). "A Note on Finding the Bridges of a Graph." Information Processing Letters 2(6), 160 a 161.
  12. Holm, J., de Lichtenberg, K. y Thorup, M. (2001). "Poly-logarithmic Deterministic Fully-Dynamic Algorithms for Connectivity, Minimum Spanning Tree, 2-Edge, and Biconnectivity." Journal of the ACM 48(4), 723 a 760.
  13. Diestel, R. (2017). Graph Theory, 5.ª edición. Graduate Texts in Mathematics 173. Berlín: Springer.

Encuentra tú mismo los eslabones débiles

Dibuja una red, ejecuta el buscador de puentes y mira cómo la búsqueda en profundidad marca cada arista que no tiene desvío. Luego añade una arista y verás desaparecer un puente.

Abrir el visualizador

Sin desvío no hay conexión

Dibuja una red, ejecuta el buscador de puentes y mira cómo una sola búsqueda en profundidad marca cada arista sin desvío. Añade una sola arista y verás desaparecer un puente.

Abrir el buscador de puentes