Submission #1146315

#TimeUsernameProblemLanguageResultExecution timeMemory
1146315aarb_.tomatexdGame (IOI14_game)C++20
0 / 100
0 ms324 KiB
#include <bits/stdc++.h>
using namespace std;

// Máximo número de ciudades (ajusta este valor según las restricciones del problema)
static const int MAX_N = 1100;
int nCities;

// Estructura Union-Find (Disjoint Set) para mantener la conectividad
int parent[MAX_N];
int compSize[MAX_N];
// Para cada representante, mantenemos la lista de vértices (ciudades) en esa componente.
vector<int> compVertices[MAX_N];

// Matriz global para marcar que la pregunta (u,v) ya se hizo.
// Se utiliza la convención: para u < v, asked[u][v] == true indica que la consulta se realizó.
bool asked[MAX_N][MAX_N];

// Función find con compresión de caminos.
int findp(int a) {
    if (parent[a] == a) return a;
    return parent[a] = findp(parent[a]);
}

// Función para unir dos componentes (por tamaño).
void unionComponents(int a, int b) {
    a = findp(a), b = findp(b);
    if (a == b) return;
    if (compSize[a] < compSize[b]) swap(a, b);
    parent[b] = a;
    compSize[a] += compSize[b];
    // Fusionamos las listas de vértices.
    for (int v : compVertices[b]) {
        compVertices[a].push_back(v);
    }
    compVertices[b].clear();
}

// Dada dos componentes (identificadas por sus representantes),
// cuenta cuántos pares (x, y) con x en el primer componente y y en el segundo ya han sido consultados.
int countAskedBetween(int compA, int compB) {
    int cnt = 0;
    for (int u : compVertices[compA]) {
        for (int v : compVertices[compB]) {
            int a = min(u, v), b = max(u, v);
            if (asked[a][b])
                cnt++;
        }
    }
    return cnt;
}

// Se llama al inicio de cada juego.
void initialize(int n) {
    nCities = n;
    // Inicializamos union-find y las listas de componentes.
    for (int i = 0; i < n; i++) {
        parent[i] = i;
        compSize[i] = 1;
        compVertices[i].clear();
        compVertices[i].push_back(i);
    }
    // Inicializamos la matriz 'asked'. Sólo consideramos u < v.
    for (int i = 0; i < n; i++) {
        for (int j = i + 1; j < n; j++) {
            asked[i][j] = false;
        }
    }
}

// Se invoca para cada pregunta: "¿existe un vuelo directo entre u y v?".
// Debe responder inmediatamente 1 (sí) o 0 (no).
int hasEdge(int u, int v) {
    // Asegurarse de trabajar con u < v para la matriz 'asked'
    if (u > v) swap(u, v);
    
    // Registrar que se realizó la consulta (u, v).
    asked[u][v] = true;
    
    // Obtenemos los representantes (componentes) de u y v.
    int ru = findp(u), rv = findp(v);
    
    if (ru == rv) {
        // Ya están conectados a través de respuestas "yes" anteriores, por lo que se responde "no".
        return 0;
    }
    
    // Si pertenecen a componentes diferentes:
    // El número total de pares entre las dos componentes es:
    int total_possible = compSize[ru] * compSize[rv];
    
    // Contamos cuántos de esos pares ya se han consultado.
    int cnt = countAskedBetween(ru, rv);
    
    // Si esta consulta es la ÚLTIMA posibilidad para conectar estas dos componentes
    // (es decir, se han consultado total_possible - 1 de los pares), debemos contestar "yes"
    // para no dejar revelada la conectividad (y así, Jian-Jia gana el juego).
    if (cnt == total_possible - 1) {
        unionComponents(ru, rv);
        return 1;
    }
    else {
        // En otro caso, contestamos "no".
        return 0;
    }
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...