Submission #1272330

#TimeUsernameProblemLanguageResultExecution timeMemory
1272330ian_otoniRace (IOI11_race)C++20
43 / 100
3096 ms35876 KiB
#include<bits/stdc++.h> #include "race.h" using namespace std; #define INF 999999999 vector<vector<pair<int, int>>> adj; vector<bool> is_removed; unordered_map<int, int> melhor; vector<int> sub; int calcula_tam_subarvores(int nodo, int pai){ sub[nodo] = 1; for(auto &p : adj[nodo]){ int filho = p.first; if(filho!=pai && !is_removed[filho]) sub[nodo] += calcula_tam_subarvores(filho, nodo); } return sub[nodo]; } int acha_centroide(int nodo, int pai, int n){ for(auto &p : adj[nodo]){ int filho = p.first; if(filho!=pai && !is_removed[filho] && sub[filho]>n/2) return acha_centroide(filho, nodo, n); } return nodo; } int ans = INF; void dfs1(int start_node, int parent_node, int k){ stack<tuple<int, int, int, int>> st; //nodo, pai, distancia e peso int initial_weight = 0; for(auto &edge : adj[start_node]){ if(edge.first==parent_node){ initial_weight = edge.second; break; } } st.push(make_tuple(start_node, parent_node, 1, initial_weight)); //coloca determinado filho do centroide na pilha while(!st.empty()){ int node, pai, distancia_da_raiz, peso_ate_araiz; tie(node, pai, distancia_da_raiz, peso_ate_araiz) = st.top(); st.pop(); //precisamos ver se existe caminho de custo k-peso_ate_araiz que termina na raiz atual int weight_needed = k-peso_ate_araiz; if(weight_needed>=0){ //nao negativo auto aux = melhor.find((weight_needed)); if(aux!=melhor.end()){ ans = min(ans, aux->second+distancia_da_raiz); } } //agora colocar os filhos na pilha for(auto &p:adj[node]){ int filho = p.first; if(filho!=pai && !is_removed[filho]){ st.push(make_tuple(filho, node, distancia_da_raiz+1, peso_ate_araiz+p.second)); } } } } void dfs2(int start_node, int parent_node, int k){ stack<tuple<int, int, int, int>> st; //nodo, pai, distancia e peso int initial_weight = 0; for(auto &edge : adj[start_node]){ if(edge.first==parent_node){ initial_weight = edge.second; break; } } st.push(make_tuple(start_node, parent_node, 1, initial_weight)); //coloca determinado filho do centroide na pilha while(!st.empty()){ int node, pai, distancia_da_raiz, peso_ate_araiz; tie(node, pai, distancia_da_raiz, peso_ate_araiz) = st.top(); st.pop(); if(peso_ate_araiz>k){ continue; } //salva os caminhos que comecam na raiz e terminam em vertices dessa subarvore if(melhor.count(peso_ate_araiz)){ melhor[peso_ate_araiz] = min(melhor[peso_ate_araiz], distancia_da_raiz); }else{ //primeira vez que este peso aparece melhor[peso_ate_araiz] = distancia_da_raiz; } //agora colocar os filhos na pilha for(auto &p:adj[node]){ int filho = p.first; if(filho!=pai && !is_removed[filho]){ st.push(make_tuple(filho, node, distancia_da_raiz+1, peso_ate_araiz+p.second)); } } } } void resolve(int nodo, int k){ calcula_tam_subarvores(nodo, -1); int centroid = acha_centroide(nodo, -1, sub[nodo]); melhor.clear(); melhor[0] = 0; //so fica no centroid e nao anda for(auto &p : adj[centroid]){ int filho = p.first; if (!is_removed[filho]){ dfs1(filho, centroid, k); dfs2(filho, centroid, k); } } is_removed[centroid] = true; for(auto &p : adj[centroid]){ int filho = p.first; if(!is_removed[filho]){ resolve(filho, k); } } return; } int best_path(int N, int K, int H[][2], int L[]) { ans = INF; adj.assign(N, vector<pair<int, int>>()); is_removed.assign(N, false); melhor.clear(); sub.assign(N, 0); for (int i = 0; i < N - 1; i++) { int u = H[i][0]; int v = H[i][1]; int w = L[i]; adj[u].push_back({v, w}); adj[v].push_back({u, w}); } resolve(0, K); if(ans == INF){ return -1; }else{ 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...