#include #include #include // Using 1-based indexing for cities const int MAXN_NODES = 100005; const int LOGN_NODES = 18; // ceil(log2(MAXN_NODES)) std::vector adj[MAXN_NODES]; int comp_id[MAXN_NODES]; bool visited_comp_dfs[MAXN_NODES]; int comp_reps[MAXN_NODES]; // Representative (root for LCA DFS) for each component ID int current_comp_id_counter; // For LCA int depth[MAXN_NODES]; int parent_lca[MAXN_NODES][LOGN_NODES]; // For Median Sum long long node_initial_weights[MAXN_NODES]; long long subtree_total_node_weight[MAXN_NODES]; long long current_total_dist_sum[MAXN_NODES]; long long min_dist_sum_for_this_comp; void find_components_dfs(int u, int c_id_val) { visited_comp_dfs[u] = true; comp_id[u] = c_id_val; for (int v : adj[u]) { if (!visited_comp_dfs[v]) { find_components_dfs(v, c_id_val); } } } void setup_lca_dfs(int u, int p, int d) { depth[u] = d; parent_lca[u][0] = p; for (int k = 1; k < LOGN_NODES; ++k) { if (parent_lca[u][k-1] == 0) parent_lca[u][k] = 0; // Optimization: if parent is 0, all higher parents are 0 else parent_lca[u][k] = parent_lca[parent_lca[u][k - 1]][k - 1]; } for (int v : adj[u]) { if (v == p) continue; setup_lca_dfs(v, u, d + 1); } } int get_lca(int u, int v) { if (depth[u] < depth[v]) std::swap(u, v); for (int k = LOGN_NODES - 1; k >= 0; --k) { if (parent_lca[u][k] != 0 && depth[u] - (1 << k) >= depth[v]) { u = parent_lca[u][k]; } } if (u == v) return u; for (int k = LOGN_NODES - 1; k >= 0; --k) { if (parent_lca[u][k] != 0 && parent_lca[v][k] != 0 && parent_lca[u][k] != parent_lca[v][k]) { u = parent_lca[u][k]; v = parent_lca[v][k]; } } return parent_lca[u][0]; } int query_dist_in_comp(int u, int v) { if (u == v) return 0; int lca_node = get_lca(u, v); return depth[u] + depth[v] - 2 * depth[lca_node]; } void calculate_median_dfs1(int u, int p) { subtree_total_node_weight[u] = node_initial_weights[u]; current_total_dist_sum[u] = 0; for (int v : adj[u]) { if (v == p) continue; calculate_median_dfs1(v, u); subtree_total_node_weight[u] += subtree_total_node_weight[v]; current_total_dist_sum[u] += current_total_dist_sum[v] + subtree_total_node_weight[v]; } } void calculate_median_dfs2(int u, int p, long long total_weight_for_comp) { min_dist_sum_for_this_comp = std::min(min_dist_sum_for_this_comp, current_total_dist_sum[u]); for (int v : adj[u]) { if (v == p) continue; current_total_dist_sum[v] = current_total_dist_sum[u] - subtree_total_node_weight[v] + (total_weight_for_comp - subtree_total_node_weight[v]); calculate_median_dfs2(v, u, total_weight_for_comp); } } int main() { std::ios_base::sync_with_stdio(false); std::cin.tie(NULL); int N_nodes, M_roads, Q_queries; std::cin >> N_nodes >> M_roads >> Q_queries; for (int i = 0; i < M_roads; ++i) { int u, v; std::cin >> u >> v; adj[u].push_back(v); adj[v].push_back(u); } current_comp_id_counter = 0; for (int i = 1; i <= N_nodes; ++i) { if (!visited_comp_dfs[i]) { current_comp_id_counter++; comp_reps[current_comp_id_counter] = i; find_components_dfs(i, current_comp_id_counter); } } for (int c = 1; c <= current_comp_id_counter; ++c) { setup_lca_dfs(comp_reps[c], 0, 0); } std::vector> relevant_nodes_lists(current_comp_id_counter + 1); long long total_travel_distance = 0; for (int i = 0; i < Q_queries; ++i) { int u, v; std::cin >> u >> v; if (comp_id[u] == comp_id[v]) { total_travel_distance += query_dist_in_comp(u, v); } else { relevant_nodes_lists[comp_id[u]].push_back(u); relevant_nodes_lists[comp_id[v]].push_back(v); } } for (int c_id = 1; c_id <= current_comp_id_counter; ++c_id) { if (relevant_nodes_lists[c_id].empty()) { continue; } for (int node_val : relevant_nodes_lists[c_id]) { node_initial_weights[node_val]++; } long long current_total_node_weight = relevant_nodes_lists[c_id].size(); int R_node = comp_reps[c_id]; calculate_median_dfs1(R_node, 0); min_dist_sum_for_this_comp = current_total_dist_sum[R_node]; calculate_median_dfs2(R_node, 0, current_total_node_weight); total_travel_distance += min_dist_sum_for_this_comp; for (int node_val : relevant_nodes_lists[c_id]) { node_initial_weights[node_val] = 0; } } std::cout << total_travel_distance << std::endl; return 0; }