제출 #337740

#제출 시각아이디문제언어결과실행 시간메모리
337740BlancaHM꿈 (IOI13_dreaming)C++14
100 / 100
108 ms11112 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, rellena dist2 con la distancia entre maxNode y el resto de nodos de la componente conexa

	queue<int> Q;
	Q.push(i);
	int u, v, t, maxNode = i;
	vector<int> vertices = {};
	dist1[i] = 0;
	while(!Q.empty()) {
		u = Q.front();
		Q.pop();
		vertices.push_back(u);
		if (dist1[u] > dist1[maxNode])
			maxNode = u;
		for (auto connection: G[u]) {
			v = connection.first;
			t = connection.second;
			if (dist1[v] > dist1[u]+t) {
				dist1[v] = dist1[u]+t;
				Q.push(v);
			}
		}
	}
	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 connection: G[u]) {
			v = connection.first;
			t = connection.second;
			if (dist2[v] > dist2[u]+t) {
				dist2[v] = dist2[u]+t;
				Q.push(v);
			}
		}
	}
	int diam = dist2[maxNode2];
	dist3[maxNode2] = 0;
	Q.push(maxNode2);
	while(!Q.empty()) {
		u = Q.front();
		Q.pop();
		for (auto connection: G[u]) {
			v = connection.first;
			t = connection.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]));
	}
	return make_pair(ecc, diam);
}

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...