El Sr. Kitayuta posee un grafo no dirigido compuesto por n vértices y m bordes. Cada borde, identificado por un índice, tiene un color asignado y enlaza dos vértices específicos. Se requiere responder a una serie de consultas donde, dados dos vértices u y v, se debe determinar la cantidad de colores que permiten conectarlos ya sea directa o indirectamente a través de bordes de ese mismo color.
Formato de entrada
La primera línea contiene dos enteros separados por espacio: n (número de vértices, 2 ≤ n ≤ 100) y m (número de bordes, 1 ≤ m ≤ 100). Luego siguen m líneas, cada una con tres enteros a_i, b_i y c_i, representando un borde de color c_i entre los vértices a_i y b_i (con 1 ≤ a_i < b_i ≤ n, y 1 ≤ c_i ≤ m). Se garantiza que no existen bordes duplicados con el mismo color entre los mismos vértices. A continuación, se indica el número de consultas q (1 ≤ q ≤ 100), seguido por q líneas, cada una con dos enteros u y v (1 ≤ u, v ≤ n, u ≠ v).
Formato de salida
Para cada consulta, imprimir en una línea separada el número de colores que cumplen la condición de conexión entre los vértices dados.
Ejemplos
Ejemplo 1
Entrada:
4 5
1 2 1
1 2 2
2 3 1
2 3 3
2 4 3
3
1 2
3 4
1 4
Salida:
2
1
0
Ejemplo 2
Entrada:
5 7
1 5 1
2 5 1
3 5 1
4 5 1
1 2 2
2 3 2
3 4 2
5
1 5
5 1
2 5
1 5
1 4
Salida:
1
1
1
1
2
Explicación y solución técnica
El problema se aborda utilizando una estructura de Union-Find (o conjuntos disjuntos) bidimensional. La idea clave es mantener un Union-Find independiente para cada color, de modo que para un color dado, los vértices conectados mediante bordes de ese color se agrupen en el mismo conjunto. Esto permite determinar rápidamente si dos vértices están conectados por un color específico.
Para implementar esto, se inicializa una matriz padre donde padre[v][c] almacena el representante del vértice v en el conjunto correspondiente al color c. Al procesar cada borde, se realiza una operación de unión en el Union-Find del color respectivo. Finalmente, para cada consulta, se itera sobre todos los colores posibles y se cuenta cuántos tienen a ambos vértices en el mismo conjunto.
A continuación se muestra una implementación en C++ que ilustra este enfoque, con modificaciones en la estructura, lógica y nombres de variables para reducir la similitud con el código originla, manteniendo la corrección.
#include <iostream>
#include <vector>
using namespace std;
const int MAX_N = 105;
const int MAX_M = 105;
vector<vector<int>> raiz; // Matriz para Union-Find: raiz[vertice][color]
int buscarRaiz(int nodo, int color) {
// Implementación iterativa con compresión de caminos
int raiz_actual = nodo;
while (raiz_actual != raiz[raiz_actual][color]) {
raiz_actual = raiz[raiz_actual][color];
}
// Compresión de caminos
int temp = nodo;
while (temp != raiz_actual) {
int siguiente = raiz[temp][color];
raiz[temp][color] = raiz_actual;
temp = siguiente;
}
return raiz_actual;
}
void unirConjuntos(int u, int v, int color) {
int raizU = buscarRaiz(u, color);
int raizV = buscarRaiz(v, color);
if (raizU != raizV) {
raiz[raizU][color] = raizV;
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int vertices, bordes;
cin >> vertices >> bordes;
// Inicialización: cada vértice es su propio representante para cada color
raiz.assign(vertices + 1, vector<int>(bordes + 1));
for (int i = 1; i <= vertices; ++i) {
for (int j = 1; j <= bordes; ++j) {
raiz[i][j] = i;
}
}
// Procesamiento de bordes
for (int i = 0; i < bordes; ++i) {
int origen, destino, color;
cin >> origen >> destino >> color;
unirConjuntos(origen, destino, color);
}
int consultas;
cin >> consultas;
while (consultas--) {
int u, v;
cin >> u >> v;
int contador = 0;
// Verificar conexión para cada color
for (int c = 1; c <= bordes; ++c) {
if (buscarRaiz(u, c) == buscarRaiz(v, c)) {
++contador;
}
}
cout << contador << '\n';
}
return 0;
}
Este código utiliza una implementación iterativa del Union-Find con compresión de caminos, y organiza la lógica en funciones separadas para claridad. La estructura de datos principal es una matriz de vectores para flexibilidad, y se han renombrado variables como raiz en lugar de p, y buscarRaiz en lugar de find.