Milk Visits
Complejidad temporal:
Hacemos una búsqueda sobre el árbol, identificando las componentes conexas de vacas que tienen todas la misma raza.
En el caso de prueba de ejemplo hay componentes conexas:
- Componente : Granjas , y
- Componente : Granja
- Componente : Granja
Luego, asignamos a las granjas de cada componente un número correspondiente a la componente en la que están. Por ejemplo, en el caso de prueba de ejemplo, la granja recibiría el número , la recibiría el número , y así sucesivamente.
Al comprobar si un granjero visitante que va de la granja a la estará contento, hay dos casos posibles:
- Las granjas y son parte de la misma componente. Esto significa que el camino entre y solo contiene vacas de la misma raza. Si el granjero prefiere leche de esta raza, debemos imprimir y en caso contrario.
- Las granjas y son parte de componentes distintas. Esto significa que el granjero siempre estará satisfecho porque el camino entre y contiene ambas razas de vacas, y por lo tanto siempre debemos imprimir .
Aquí hay un recorrido de las consultas del caso de prueba de ejemplo:
- Las granjas y están en la misma componente, y como la vaca preferida del Granjero es Holstein, estará satisfecho. ()
- Las granjas y están en la misma componente, pero como la vaca preferida del Granjero es Guernsey, estará insatisfecho. ()
- Las granjas y están en componentes distintas, así que el Granjero estará satisfecho. ()
- Misma lógica que la consulta . ()
- La granja es Guernsey, y la vaca preferida del Granjero es Holstein, estará insatisfecho. ()
#include <algorithm>
#include <cassert>
#include <fstream>
#include <iostream>
#include <vector>
using std::cout;
using std::endl;
using std::vector;
int main() {
std::ifstream read("milkvisits.in");
int farm_num;
int query_num;
read >> farm_num >> query_num;
vector<char> farms(farm_num);
for (char &f : farms) {
read >> f;
assert(f == 'G' || f == 'H');
}
vector<vector<int>> neighbors(farm_num);
for (int f = 0; f < farm_num - 1; f++) {
int f1, f2;
read >> f1 >> f2;
f1--;
f2--;
neighbors[f1].push_back(f2);
neighbors[f2].push_back(f1);
}
// Procesamos el árbol y detectamos las distintas componentes
int component_num = 0;
vector<int> component(farm_num, -1);
for (int f = 0; f < farm_num; f++) {
// No procesamos una granja si ya fue visitada
if (component[f] != -1) { continue; }
vector<int> frontier{f};
char type = farms[f];
while (!frontier.empty()) {
int curr = frontier.back();
frontier.pop_back();
// Asignamos el número de componente actual a la granja
component[curr] = component_num;
for (int n : neighbors[curr]) {
// Visitamos un vecino si es nuevo y es del mismo tipo
if (farms[n] == type && component[n] == -1) { frontier.push_back(n); }
}
}
component_num++;
}
std::ofstream written("milkvisits.out");
for (int q = 0; q < query_num; q++) {
int a, b;
char milk;
read >> a >> b >> milk;
a--;
b--;
if (component[a] == component[b]) {
/*
* Si a y b están en la misma componente,
* comprobamos si el tipo de leche es el que el granjero prefiere
*/
written << (farms[a] == milk);
} else {
// Imprimimos 1 en caso contrario porque se visitarán ambos tipos de leche
written << 1;
}
}
}import java.io.*;
import java.util.*;
public class MilkVisits {
public static void main(String[] args) throws IOException {
BufferedReader read = new BufferedReader(new FileReader("milkvisits.in"));
StringTokenizer initial = new StringTokenizer(read.readLine());
int farmNum = Integer.parseInt(initial.nextToken());
int queryNum = Integer.parseInt(initial.nextToken());
String farms = read.readLine();
List<Integer>[] neighbors = new ArrayList[farmNum];
for (int f = 0; f < farmNum; f++) { neighbors[f] = new ArrayList<>(); }
for (int f = 0; f < farmNum - 1; f++) {
StringTokenizer road = new StringTokenizer(read.readLine());
int f1 = Integer.parseInt(road.nextToken()) - 1;
int f2 = Integer.parseInt(road.nextToken()) - 1;
neighbors[f1].add(f2);
neighbors[f2].add(f1);
}
// Procesamos el árbol y detectamos las distintas componentes
int componentNum = 0;
int[] component = new int[farmNum];
Arrays.fill(component, -1);
for (int f = 0; f < farmNum; f++) {
// No procesamos una granja si ya fue visitada
if (component[f] != -1) { continue; }
ArrayDeque<Integer> frontier = new ArrayDeque<>();
frontier.add(f);
char type = farms.charAt(f);
while (!frontier.isEmpty()) {
int curr = frontier.poll();
// Asignamos el número de componente actual a la granja
component[curr] = componentNum;
for (int n : neighbors[curr]) {
// Visitamos un vecino si es nuevo y es del mismo tipo
if (farms.charAt(n) == type && component[n] == -1) {
frontier.add(n);
}
}
}
componentNum++;
}
PrintWriter written = new PrintWriter("milkvisits.out");
for (int q = 0; q < queryNum; q++) {
StringTokenizer query = new StringTokenizer(read.readLine());
int a = Integer.parseInt(query.nextToken()) - 1;
int b = Integer.parseInt(query.nextToken()) - 1;
char milk = query.nextToken().charAt(0);
if (component[a] == component[b]) {
/*
* Si a y b están en la misma componente,
* comprobamos si el tipo de leche es el que el granjero
* prefiere
*/
written.print(farms.charAt(a) == milk ? 1 : 0);
} else {
// Imprimimos 1 en caso contrario porque se visitarán ambos tipos de leche
written.print(1);
}
}
written.close();
}
}with open("milkvisits.in") as read:
farm_num, query_num = [int(i) for i in read.readline().split()]
farms = read.readline()
neighbors = [[] for _ in range(farm_num)]
for f in range(farm_num - 1):
f1, f2 = [int(i) - 1 for i in read.readline().split()]
neighbors[f1].append(f2)
neighbors[f2].append(f1)
queries = []
for _ in range(query_num):
query = read.readline().split()
query[0], query[1] = int(query[0]) - 1, int(query[1]) - 1
queries.append(query)
# Procesamos el árbol y detectamos las distintas componentes
component_num = 0
component = [-1 for _ in range(farm_num)]
for f in range(farm_num):
# No procesamos una granja si ya fue visitada
if component[f] != -1:
continue
frontier = [f]
curr_type = farms[f]
while frontier:
curr = frontier.pop()
# Asignamos el número de componente actual a la granja
component[curr] = component_num
for n in neighbors[curr]:
# Visitamos un vecino si es nuevo y es del mismo tipo
if farms[n] == curr_type and component[n] == -1:
frontier.append(n)
component_num += 1
with open("milkvisits.out", "w") as written:
for a, b, milk in queries:
if component[a] == component[b]:
"""
Si a y b están en la misma componente,
comprobamos si el tipo de leche es el que el granjero prefiere
"""
print(1 if farms[a] == milk else 0, end="", file=written)
else:
# Imprimimos 1 en caso contrario porque se visitarán ambos tipos de leche
print(1, end="", file=written)
print(file=written)