Un puente (o bridge) es una arista que, al eliminarla, incrementa la cantidad de componentes conexas de un grafo no dirigido. Identificarlos permite conocer puntos críticos de conectividad.
u -- v es puente si no existe ningún camino alternativo entre u y v sin usar esa arista.El algoritmo de Tarjan usa DFS con tiempos de descubrimiento tin[] y valores low[] que representan el tiempo mínimo alcanzable por back-edges.
timer = 0; al entrar a un nodo u, asignamos tin[u] = low[u] = timer++.v: si es el padre en el árbol, se ignora; si no está visitado, se desciende y se actualiza low[u] = min(low[u], low[v]).v, la arista u -- v es puente si low[v] > tin[u].v ya estaba visitado (back-edge), actualizamos low[u] = min(low[u], tin[v]).Simulador de detección de puentes
La detección de puentes es esencial en:
Implementación de Tarjan sobre lista de adyacencia. Imprime todas las aristas puente encontradas.
#include <stdio.h>
#include <stdlib.h>
typedef struct Arista {
int destino;
struct Arista *sig;
} Arista;
typedef struct {
int n;
Arista **listas;
} Grafo;
Grafo crearGrafo(int n) {
Grafo g;
g.n = n;
g.listas = calloc(n, sizeof(Arista *));
return g;
}
void agregarAristaNoDirigida(Grafo *g, int u, int v) {
Arista *a = malloc(sizeof(Arista));
a->destino = v;
a->sig = g->listas[u];
g->listas[u] = a;
Arista *b = malloc(sizeof(Arista));
b->destino = u;
b->sig = g->listas[v];
g->listas[v] = b;
}
void dfsPuentes(const Grafo *g, int u, int padre, int *visitado, int *tin, int *low, int *timer) {
visitado[u] = 1;
tin[u] = low[u] = (*timer)++;
for (Arista *it = g->listas[u]; it; it = it->sig) {
int v = it->destino;
if (v == padre) continue;
if (!visitado[v]) {
dfsPuentes(g, v, u, visitado, tin, low, timer);
if (low[v] > tin[u]) {
printf("Puente: %d -- %d\n", u, v);
}
if (low[v] < low[u]) low[u] = low[v];
} else {
if (tin[v] < low[u]) low[u] = tin[v];
}
}
}
void encontrarPuentes(const Grafo *g) {
int *visitado = calloc(g->n, sizeof(int));
int *tin = malloc(g->n * sizeof(int));
int *low = malloc(g->n * sizeof(int));
int timer = 0;
for (int u = 0; u < g->n; u++) {
if (!visitado[u]) {
dfsPuentes(g, u, -1, visitado, tin, low, &timer);
}
}
free(visitado);
free(tin);
free(low);
}
int main(void) {
Grafo g = crearGrafo(7);
agregarAristaNoDirigida(&g, 0, 1);
agregarAristaNoDirigida(&g, 1, 2);
agregarAristaNoDirigida(&g, 2, 0);
agregarAristaNoDirigida(&g, 1, 3); /* puente */
agregarAristaNoDirigida(&g, 3, 4);
agregarAristaNoDirigida(&g, 4, 5);
agregarAristaNoDirigida(&g, 5, 3); /* ciclo 3-4-5 */
agregarAristaNoDirigida(&g, 4, 6); /* puente */
printf("Puentes del grafo:\n");
encontrarPuentes(&g);
return 0;
}