Submission #790200

#TimeUsernameProblemLanguageResultExecution timeMemory
790200jophyyjhDreaming (IOI13_dreaming)C++14
0 / 100
1088 ms11804 KiB
/** * Not too difficult~ Let P_1, P_2, ..., P_k be the connected components of the graph. * Clearly, every P_i is a tree. * [Lemma] There exists a way of connecting the edges that minimizes the resulting tree's * diameter in such a way that, * for a fixed i, all edges connecting P_i and another P_j (i!=j) are * incident to the same node in P_i. * This is a greedy strategy. Greedily, we can again prove that the node in P_i has the * smallest f(node) := max{ dist(node, n2) : n2 is a node in P_i different from node }. * Next, we can view each P_i as a "super node" and consider how we shall connect them. * Since we have to minimize the diameter, we shall connect the super nodes to form a star * graph, whose diameter is at most 2. Again, we shall be greedy: the center super node in * our star graph should be the component with the largest f(chosen_node_in_the_comp). * * Time Complexity: O(n * log(n)) (Optimal: O(n); O(n * log(n)) is just simpler) * Implementation 1 (Full solution, greedy, tree dp) */ #include <bits/stdc++.h> #include "dreaming.h" typedef std::vector<int> vec; struct edge_t { int node, len; }; typedef std::vector<edge_t> adj_list_t; std::vector<adj_list_t> trees; vec down, down_node, down2, up; std::vector<bool> visited; int diameter = 0; // diameter of the resulting graph void dfs1(int k, int parent) { visited[k] = true; for (const edge_t& e : trees[k]) { int child = e.node; if (parent == child) continue; dfs1(child, k); int d = down[child] + e.len; if (d > down[k]) down2[k] = down[k], down[k] = d, down_node[k] = child; else down2[k] = std::max(down2[k], d); } } int dfs2(int k, int parent) { int cost = std::max(up[k], down[k]); diameter = std::max(diameter, cost); for (const edge_t& e : trees[k]) { int child = e.node; if (parent == child) continue; up[child] = (down_node[k] != child ? down[k] : down2[k]) + e.len; up[child] = std::max(up[child], up[k] + e.len); cost = std::min(cost, dfs2(child, k)); dfs2(child, k); } return cost; } int travelTime(int n, int m, int L, int A[], int B[], int T[]) { trees.assign(n, adj_list_t()); for (int k = 0; k < m; k++) { trees[A[k]].push_back(edge_t{B[k], T[k]}); trees[B[k]].push_back(edge_t{A[k], T[k]}); } visited.assign(n, false); down.assign(n, 0); down_node.resize(n); down2.assign(n, 0); up.assign(n, 0); vec costs; for (int k = 0; k < n; k++) { if (visited[k]) continue; dfs1(k, -1); costs.push_back(dfs2(k, -1)); } // std::sort(costs.rbegin(), costs.rend()); // while (int(costs.size()) > 3) // costs.pop_back(); // for (int i = 1; i < int(costs.size()); i++) // costs[i] += L; // std::sort(costs.rbegin(), costs.rend()); // diameter = std::max(diameter, costs[0] + (int(costs.size()) > 1 ? costs[1] : 0)); return diameter; }
#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...