Submission #337743

#TimeUsernameProblemLanguageResultExecution timeMemory
337743BlancaHMDreaming (IOI13_dreaming)C++14
100 / 100
133 ms10728 KiB
#include <iostream> #include <vector> #include <queue> #include <map> #include <unordered_map> #include <algorithm> #include "dreaming.h" using namespace std; typedef vector<int> vi; typedef vector<vi> vvi; typedef pair<int, int> pii; typedef vector<pii> vpii; typedef vector<vpii> vvpii; pii calcDist(int i, vvpii & G, vi & dist1, vi & dist2, vi & dist3) { // calcularemos el diámetro con el método de las dos colas, que primero busca el nodo más lejano de la raíz i (maxNode) // después, rellenamos dist2 con la distancia entre maxNode y el resto de nodos de la componente conexa // así, encuentra el nodo más lejano de maxNode (maxNode2). El diámetro es la distancia entre maxNode y maxNode2. // finalmente, rellenamos dist3 con la distancia entre maxNode2 y el resto de nodos de la componente conexa // la eccentricidad de cada vértice será el máximo entre la distancia con maxNode y la distancia con maxNode2 queue<int> Q; Q.push(i); int u, v, t, maxNode = i; vector<int> vertices = {}; // aquí guardaremos los vértices de la componente conexa dist1[i] = 0; while(!Q.empty()) { u = Q.front(); Q.pop(); vertices.push_back(u); // añadimos u a la lista de vértices de la componente conexa if (dist1[u] > dist1[maxNode]) // actualizamos maxNode si procede maxNode = u; for (auto conexion: G[u]) { // procesamos las conexiones de u v = conexion.first; t = conexion.second; if (dist1[v] > dist1[u]+t) { // v no visitado dist1[v] = dist1[u]+t; // actualizamos la distancia de v en base a la de u Q.push(v); } } } // hacemos lo mismo para maxNode dist2[maxNode] = 0; Q.push(maxNode); int maxNode2 = maxNode; while(!Q.empty()) { u = Q.front(); Q.pop(); if (dist2[u] > dist2[maxNode2]) maxNode2 = u; for (auto conexion: G[u]) { v = conexion.first; t = conexion.second; if (dist2[v] > dist2[u]+t) { dist2[v] = dist2[u]+t; Q.push(v); } } } // hacemos lo mismo para maxNode2 dist3[maxNode2] = 0; Q.push(maxNode2); while(!Q.empty()) { u = Q.front(); Q.pop(); for (auto conexion: G[u]) { v = conexion.first; t = conexion.second; if (dist3[v] > dist3[u]+t) { dist3[v] = dist3[u]+t; Q.push(v); } } } int ecc = 1e9; for (auto vert: vertices) { ecc = min(ecc, max(dist2[vert], dist3[vert])); // calculamos la eccentricidad de vert y actualizamos el mínimo } return make_pair(ecc, dist2[maxNode2]); } int travelTime(int N, int M, int L, int A[], int B[], int T[]) { // primero, pasamos las listas de aristas a un grafo en formato "adjacency list" // guardamos cada arista en la lista de sus dos nodos, ya que el grafo es bidireccional vvpii G(N, vpii()); for (int i = 0; i < M; i++) { G[A[i]].push_back(make_pair(B[i], T[i])); G[B[i]].push_back(make_pair(A[i], T[i])); } int CC = 0; // número de componentes conexas del grafo (un bosque) vi diam = {}; // diámetro de las componentes conexas vi ecc = {}; // guarda para cada componente conexa la eccentricidad del vértice con menor eccentricidad del grafo vi dist1; // guarda la distancia entre la raíz de la componente conexa y cada uno de sus nodos vi dist2; // guarda la distancia entre el nodo más lejano de la raíz de la componente conexa y el resto de sus nodos vi dist3; // guarda la distancia entre el nodo que define dist2 y el resto de nodos de la componente conexa dist1 = dist2 = dist3 = vi(N, 1e9); // asignamos "infinito" como valores iniciales para las distancias pii curCC; // aquí guardamos el valor de for (int i = 0; i < N; i++) { if (dist1[i] == 1e9) { // nodo i no visitado aún curCC = calcDist(i, G, dist1, dist2, dist3); // {ecc, diam} de la componente conexa de i ecc.push_back(curCC.first); diam.push_back(curCC.second); CC++; } } // para minimizar el camino más largo, guardaremos el grafo como una estrella, conectando los centros de cada // componente conexa todas al centro de la componente conexa con mayor eccentricidad // así, la respuesta será una de las siguientes: // 1. la componente conexa con el mayor diámetro // 2. la mayor distancia entre el centro de las dos componentes con mayor eccentricidad // 3. la distancia entre la segunda y la tercera mayor eccentricidad, pasando por el centro medio // guardamos en ecc[0] la eccentricidad mayor for (int i = 1; i < CC; i++) { if (ecc[i] > ecc[0]) swap(ecc[0], ecc[i]); } int ans = 0; if (CC > 1) { // guardamos en ecc[1] la sedunda eccentricidad mayor for (int i = 2; i < CC; i++) { if (ecc[i] > ecc[1]) swap(ecc[i], ecc[1]); } ans = ecc[0]+ecc[1]+L; // posibilidad 2 if (CC > 2) { // guardamos en ecc[2] la tercera eccentricidad mayor for (int i = 3; i < CC; i++) { if (ecc[i] > ecc[2]) swap(ecc[i], ecc[2]); } ans = max(ans, ecc[1]+ecc[2]+2*L); // posibilidad 3 } } for (int i = 0; i < CC; i++) { ans = max(ans, diam[i]); // posibilidad 1 } return ans; }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...