Grafosc++BFSgrafoscamino más corto
BFS en Grafos
Búsqueda en amplitud aplicada a grafos para caminos más cortos y exploraciones nivel a nivel
OOI Oaxaca9 de febrero de 20264 min read
BFS en grafos: repaso rápido
Ya vimos BFS en la sección de búsquedas. Aquí nos enfocamos en sus aplicaciones específicas en grafos.
Camino más corto (sin pesos)
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
const int MAXN = 100005;
vector<int> adj[MAXN];
int dist[MAXN];
int padre[MAXN];
bool vis[MAXN];
void bfs(int inicio, int n) {
fill(dist, dist + n + 1, -1);
fill(padre, padre + n + 1, -1);
queue<int> q;
q.push(inicio);
dist[inicio] = 0;
while (!q.empty()) {
int u = q.front(); q.pop();
for (int v : adj[u]) {
if (dist[v] == -1) {
dist[v] = dist[u] + 1;
padre[v] = u;
q.push(v);
}
}
}
}
vector<int> reconstruirCamino(int destino) {
vector<int> camino;
for (int v = destino; v != -1; v = padre[v]) {
camino.push_back(v);
}
reverse(camino.begin(), camino.end());
return camino;
}
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);
adj[v].push_back(u);
}
int origen, destino;
cin >> origen >> destino;
bfs(origen, n);
if (dist[destino] == -1) {
cout << "No hay camino" << endl;
} else {
cout << "Distancia: " << dist[destino] << endl;
cout << "Camino: ";
for (int v : reconstruirCamino(destino)) {
cout << v << " ";
}
cout << endl;
}
return 0;
}
BFS 0-1
Cuando las aristas tienen peso 0 o 1, puedes usar una variante de BFS con un deque en lugar de una cola normal:
void bfs01(int inicio, int n) {
fill(dist, dist + n + 1, INT_MAX);
deque<int> dq;
dist[inicio] = 0;
dq.push_front(inicio);
while (!dq.empty()) {
int u = dq.front(); dq.pop_front();
for (auto [v, w] : adj[u]) { // adj almacena {vecino, peso}
if (dist[u] + w < dist[v]) {
dist[v] = dist[u] + w;
if (w == 0) {
dq.push_front(v); // Peso 0: alta prioridad
} else {
dq.push_back(v); // Peso 1: baja prioridad
}
}
}
}
}
Complejidad: , igual que BFS normal.
Verificar si un grafo es bipartito
Un grafo es bipartito si puedes colorear sus nodos con 2 colores sin que dos nodos adyacentes tengan el mismo color.
int color[MAXN]; // -1 = sin color
bool esBipartito(int inicio) {
queue<int> q;
q.push(inicio);
color[inicio] = 0;
while (!q.empty()) {
int u = q.front(); q.pop();
for (int v : adj[u]) {
if (color[v] == -1) {
color[v] = 1 - color[u];
q.push(v);
} else if (color[v] == color[u]) {
return false; // Conflicto
}
}
}
return true;
}
BFS multi-fuente
Calcular la distancia mínima desde cualquier fuente:
void bfsMultiFuente(vector<int> &fuentes, int n) {
fill(dist, dist + n + 1, -1);
queue<int> q;
for (int f : fuentes) {
dist[f] = 0;
q.push(f);
}
while (!q.empty()) {
int u = q.front(); q.pop();
for (int v : adj[u]) {
if (dist[v] == -1) {
dist[v] = dist[u] + 1;
q.push(v);
}
}
}
}
Ejercicio de práctica
Dado un grafo no dirigido con N nodos y M aristas, encuentra la distancia más corta entre los nodos S y T. Si no hay camino, imprime -1.
Ver solución
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
vector<int> adj[100005];
int dist[100005];
int main() {
int n, m, s, t;
cin >> n >> m >> s >> t;
for (int i = 0; i < m; i++) {
int u, v;
cin >> u >> v;
adj[u].push_back(v);
adj[v].push_back(u);
}
fill(dist, dist + n + 1, -1);
queue<int> q;
q.push(s);
dist[s] = 0;
while (!q.empty()) {
int u = q.front(); q.pop();
for (int v : adj[u]) {
if (dist[v] == -1) {
dist[v] = dist[u] + 1;
q.push(v);
}
}
}
cout << dist[t] << endl;
return 0;
}
