Grafos Avanzadosc++ciclosgrafosDFS
Detección de Ciclos
Detecta ciclos en grafos dirigidos y no dirigidos
OOI Oaxaca9 de febrero de 20263 min read
Ciclos en grafos no dirigidos
Un ciclo existe si encontramos un vecino ya visitado que no es el padre del nodo actual.
vector<int> adj[MAXN];
bool vis[MAXN];
bool tieneCiclo = false;
void dfs(int u, int padre) {
vis[u] = true;
for (int v : adj[u]) {
if (!vis[v]) {
dfs(v, u);
} else if (v != padre) {
tieneCiclo = true;
}
}
}
También puedes usar Union-Find: si al agregar una arista, ambos extremos ya están en la misma componente, hay ciclo.
bool hayCicloUF(int n, vector<pair<int,int>> &aristas) {
inicializar(n);
for (auto [u, v] : aristas) {
if (encontrar(u) == encontrar(v)) return true;
unir(u, v);
}
return false;
}
Ciclos en grafos dirigidos
Usamos la coloración blanco/gris/negro:
int color[MAXN]; // 0=blanco, 1=gris, 2=negro
bool dfsCiclo(int u) {
color[u] = 1; // Gris: en proceso
for (int v : adj[u]) {
if (color[v] == 1) return true; // Back edge → ciclo
if (color[v] == 0 && dfsCiclo(v)) return true;
}
color[u] = 2; // Negro: terminado
return false;
}
bool hayCicloDirigido(int n) {
fill(color, color + n + 1, 0);
for (int i = 1; i <= n; i++) {
if (color[i] == 0 && dfsCiclo(i)) return true;
}
return false;
}
Encontrar un ciclo (no solo detectarlo)
int padre_ciclo[MAXN];
int inicio_ciclo = -1, fin_ciclo = -1;
bool dfsBuscarCiclo(int u) {
color[u] = 1;
for (int v : adj[u]) {
if (color[v] == 1) {
fin_ciclo = u;
inicio_ciclo = v;
return true;
}
if (color[v] == 0) {
padre_ciclo[v] = u;
if (dfsBuscarCiclo(v)) return true;
}
}
color[u] = 2;
return false;
}
void imprimirCiclo() {
vector<int> ciclo;
ciclo.push_back(inicio_ciclo);
for (int v = fin_ciclo; v != inicio_ciclo; v = padre_ciclo[v]) {
ciclo.push_back(v);
}
ciclo.push_back(inicio_ciclo);
reverse(ciclo.begin(), ciclo.end());
for (int v : ciclo) cout << v << " ";
cout << endl;
}
Ejercicio de práctica
Dado un grafo dirigido, imprime "SI" si tiene un ciclo, "NO" si no.
Ver solución
#include <iostream>
#include <vector>
using namespace std;
vector<int> adj[100005];
int color[100005];
bool dfs(int u) {
color[u] = 1;
for (int v : adj[u]) {
if (color[v] == 1) return true;
if (color[v] == 0 && dfs(v)) return true;
}
color[u] = 2;
return false;
}
int main() {
int n, m;
cin >> n >> m;
for (int i = 0; i < m; i++) {
int u, v; cin >> u >> v;
adj[u].push_back(v);
}
for (int i = 1; i <= n; i++) {
if (color[i] == 0 && dfs(i)) {
cout << "SI" << endl;
return 0;
}
}
cout << "NO" << endl;
return 0;
}
