답안 #366923

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
366923 2021-02-15T18:22:29 Z BlancaHM 꿈 (IOI13_dreaming) C++14
컴파일 오류
0 ms 0 KB
#include <vector>
#include <queue>
using namespace std;

pair<int,int> calcDist(int i, vector<vector<pair<int, int>>> & listaAdyacencia, vector<int> & dist1, vector<int> & dist2, vector<int> & 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: listaAdyacencia[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: listaAdyacencia[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: listaAdyacencia[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
	vector<vector<pair<int, int>>> listaAdyacencia(N);
	for (int i = 0; i < M; i++) {
		listaAdyacencia[A[i]].push_back(make_pair(B[i], T[i]));
		listaAdyacencia[B[i]].push_back(make_pair(A[i], T[i]));
	}
	int CC = 0; // número de componentes conexas del grafo (un bosque)
	vector<int> diam; // diámetro de las componentes conexas
	vector<int> ecc; // guarda para cada componente conexa la eccentricidad del vértice con menor eccentricidad del grafo
	vector<int> dist1; // guarda la distancia entre la raíz de la componente conexa y cada uno de sus nodos
    vector<int> dist2; // guarda la distancia entre el nodo más lejano de la raíz de la componente conexa y el resto de sus nodos
	vector<int> dist3; // guarda la distancia entre el nodo que define dist2 y el resto de nodos de la componente conexa
    dist1 = dist2 = dist3 = vector<int>(N, 1e9); // asignamos "infinito" como valores iniciales para las distancias
    pair<int, int> curCC; // aquí guardamos el valor devuelto de la componente conexa
    for (int i = 0; i < N; i++) {
	    if (dist1[i] == 1e9) { // nodo i no visitado aún
	    	curCC = calcDist(i, listaAdyacencia, 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;
}

Compilation message

/tmp/ccv0azhg.o: In function `main':
grader.c:(.text.startup+0xc9): undefined reference to `travelTime'
collect2: error: ld returned 1 exit status