#include "towns.h"
#include <algorithm>
#include <cassert>
#include <limits>
#include <utility>
#include <vector>
int hubDistance(int N, int) {
std::vector<int> distances_from_0(N);
for (int i = 1; i < N; i++) {
distances_from_0[i] = getDistance(0, i);
}
int u = std::max_element(distances_from_0.begin(), distances_from_0.end()) -
distances_from_0.begin();
std::vector<int> distances_from_u(N);
distances_from_u[0] = distances_from_0[u];
for (int i = 1; i < N; i++) {
if (i == u)
continue;
distances_from_u[i] = getDistance(u, i);
}
int v = std::max_element(distances_from_u.begin(), distances_from_u.end()) -
distances_from_u.begin();
int diameter = distances_from_u[v];
// y = connection point from [i] to 0u path.
std::vector<int> distance_y_to_u(N);
for (int i = 0; i < N; i++) {
distance_y_to_u[i] =
(distances_from_u[i] + distances_from_0[u] - distances_from_0[i]) / 2;
}
int radius = std::numeric_limits<int>::max();
for (int i = 0; i < N; i++) {
// if both on 0u and vu path
if (distance_y_to_u[i] <= distance_y_to_u[v]) {
int r = std::max(distance_y_to_u[i], diameter - distance_y_to_u[i]);
if (r < radius)
radius = r;
}
}
int max_size = N / 2;
int distance_center_u = -1;
int distance_other_center_u = -1;
for (int i = 0; i < N; i++) {
int dist = distance_y_to_u[i];
if (dist == radius)
distance_center_u = dist;
else if (dist == diameter - radius)
distance_other_center_u = dist;
}
if (distance_center_u == -1) {
distance_center_u = distance_other_center_u;
} else if (distance_other_center_u != -1) {
assert(distance_center_u > distance_other_center_u);
int subtree_size_center = 0;
for (int i = 0; i < N; i++) {
if (distance_y_to_u[i] >= distance_center_u) {
subtree_size_center++;
}
}
if (subtree_size_center * 2 == N) {
return radius;
} else if (subtree_size_center * 2 < N) {
distance_center_u = distance_other_center_u;
}
}
// From here on, distance_center_u is the only possible candidate.
std::vector<int> connected_to_x;
int connected_before_x = 0;
int connected_after_x = 0;
for (int i = 0; i < N; i++) {
if (distance_y_to_u[i] < distance_center_u) {
connected_before_x++;
} else if (distance_y_to_u[i] > distance_center_u) {
connected_after_x++;
} else {
connected_to_x.push_back(i);
}
}
if (connected_before_x > max_size || connected_after_x > max_size) {
return -radius;
}
auto are_connected_with_same_edge = [&](int a, int b) {
int a_from_center = distances_from_u[a] - distance_y_to_u[a];
int b_from_center = distances_from_u[b] - distance_y_to_u[b];
return getDistance(a, b) != a_from_center + b_from_center;
};
std::vector<std::vector<int>> bags;
std::vector<std::vector<int>> dead_bags;
for (auto z : connected_to_x) {
bags.push_back({z});
}
while (bags.size() > 1) {
std::vector<std::vector<int>> new_bags;
if (bags.size() % 2 == 1) {
new_bags.push_back(bags.back());
bags.pop_back();
}
for (int i = 0; 2 * i < bags.size(); i++) {
auto bag1 = bags[2 * i];
auto bag2 = bags[2 * i + 1];
if (are_connected_with_same_edge(bag1[0], bag2[0])) {
new_bags.push_back(bag1);
new_bags.back().insert(new_bags.back().end(), bag2.begin(), bag2.end());
} else {
dead_bags.push_back(bag1);
dead_bags.push_back(bag2);
}
}
bags = new_bags;
}
if (bags.empty()) {
return radius;
}
int largest_subtree_size = bags[0].size();
for (auto &b : dead_bags) {
if (are_connected_with_same_edge(b[0], bags[0][0])) {
largest_subtree_size += b.size();
}
}
return largest_subtree_size > max_size ? -radius : radius;
}
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |