Prueba de bipartición por BFS

Definición

Algoritmo lineal en tiempo que determina si un grafo no dirigido es un grafo bipartito y, en caso afirmativo, produce una -coloración válida, o en caso negativo, exhibe un ciclo de longitud impar que certifica formalmente la imposibilidad de bipartición.

Fundamento teórico: Partición por capas BFS

Sea conexo y sean las capas de distancia producidas por BFS iniciando en un vértice arbitrario ().

Por la propiedad del árbol BFS, toda arista une vértices cuyos niveles difieren a lo más en 1 (). Por ende, solo existen dos casos posibles para cada arista:

  1. Une vértices de niveles contiguos ( y ).
  2. Une vértices dentro del mismo nivel ( y ).

Lema de Bipartición en Capas BFS

Sea conexo con capas BFS . Se cumple exactamente una de las siguientes dos afirmaciones:

  1. Caso (i): Ninguna arista de une dos nodos de la misma capa es bipartito. La bipartición válida es:
  2. Caso (ii): Existe una arista tal que contiene un ciclo de longitud impar y, por tanto, no es bipartito.

Demostración del Caso (ii) y construcción del ciclo impar

Sea una arista con . En el árbol BFS, trazamos los caminos desde y desde hacia la raíz hasta encontrar su ancestro común más cercano (lowest common ancestor), , ubicado en algún nivel ():

  • El camino de a en el árbol tiene longitud .
  • El camino de a en el árbol tiene longitud .
  • La arista directa tiene longitud .

El ciclo cerrado tiene longitud total:

Como es estrictamente par para cualquier entero , es estrictamente impar.

flowchart TD
  z((z = lca))
  z --- px["Camino de longitud j - i"]
  z --- py["Camino de longitud j - i"]
  px --- x((x ∈ Lj))
  py --- y((y ∈ Lj))
  x ===|Arista e de longitud 1| y

Algoritmo y análisis de complejidad

def es_bipartito(G, s):
    # 1. Ejecutar BFS y etiquetar niveles
    nivel = {s: 0}
    cola = [s]
    while cola:
        u = cola.pop(0)
        for v in G.vecinos(u):
            if v not in nivel:
                nivel[v] = nivel[u] + 1
                cola.append(v)
            elif nivel[v] == nivel[u]:
                # Encontrada arista en la misma capa
                return False, "Ciclo impar detectado entre " + str(u) + " y " + str(v)
    return True, nivel
  • Tiempo de ejecución: utilizando listas de adyacencia (igual que BFS estándar).
  • Espacio adicional: para almacenar los niveles y la cola.

Relaciones

Procedencia