Un punto de articulación es un vértice que, al eliminarlo junto con sus aristas incidentes, incrementa la cantidad de componentes conexas del grafo no dirigido. Detectarlos revela nodos críticos de conectividad.
El algoritmo de Tarjan para puntos de articulación reutiliza tin[] y low[] con DFS:
tin[u] = low[u] = timer++ al descubrir u.v: si es el padre, se ignora; si no está visitado, se desciende y luego low[u] = min(low[u], low[v]).low[v] >= tin[u], el nodo u separa el subárbol de v del resto.Simulador de puntos de articulación
Implementación con listas de adyacencia que imprime todos los puntos de articulación encontrados.
#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 dfsArticulacion(const Grafo *g, int u, int padre, int *visitado, int *tin, int *low, int *timer, int *hijoRaiz, int *esArticulacion) {
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]) {
if (padre == -1) (*hijoRaiz)++; /* contar hijos de la raiz */
dfsArticulacion(g, v, u, visitado, tin, low, timer, hijoRaiz, esArticulacion);
if (low[v] >= tin[u]) esArticulacion[u] = 1;
if (low[v] < low[u]) low[u] = low[v];
} else {
if (tin[v] < low[u]) low[u] = tin[v];
}
}
}
void encontrarPuntosArticulacion(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 *esArticulacion = calloc(g->n, sizeof(int));
int timer = 0;
for (int u = 0; u < g->n; u++) {
if (!visitado[u]) {
int hijoRaiz = 0;
dfsArticulacion(g, u, -1, visitado, tin, low, &timer, &hijoRaiz, esArticulacion);
if (hijoRaiz < 2) esArticulacion[u] = 0;
}
}
printf("Puntos de articulacion:\n");
for (int i = 0; i < g->n; i++) {
if (esArticulacion[i]) {
printf(" - %d\n", i);
}
}
free(visitado);
free(tin);
free(low);
free(esArticulacion);
}
int main(void) {
Grafo g = crearGrafo(7);
agregarAristaNoDirigida(&g, 0, 1);
agregarAristaNoDirigida(&g, 1, 2);
agregarAristaNoDirigida(&g, 2, 0); /* ciclo 0-1-2 */
agregarAristaNoDirigida(&g, 1, 3); /* 1 es articulacion */
agregarAristaNoDirigida(&g, 3, 4);
agregarAristaNoDirigida(&g, 4, 5);
agregarAristaNoDirigida(&g, 5, 3); /* ciclo 3-4-5 */
agregarAristaNoDirigida(&g, 4, 6); /* 4 es articulacion */
encontrarPuntosArticulacion(&g);
return 0;
}