Submission #677064

#TimeUsernameProblemLanguageResultExecution timeMemory
677064CyanmondRailway (BOI17_railway)C++17
100 / 100
334 ms65736 KiB
#include <bits/stdc++.h> struct LCA { int n; int logn; std::vector<std::vector<int>> tree; std::vector<int> depth; std::vector<int> parent; std::vector<std::vector<int>> ancestors; LCA(const std::vector<std::vector<int>> &treee) { tree = treee; n = (int)tree.size(); logn = 0; while ((1 << logn) < n) { ++logn; } parent.resize(n); depth.resize(n); dfs(0, -1, 0); make_table(); } void make_table() { ancestors.resize(logn + 1); ancestors[0] = parent; for (int d = 0; d < logn; ++d) { ancestors[d + 1].resize(n); for (int i = 0; i < n; ++i) { const int t = ancestors[d][i]; if (t == -1) { ancestors[d + 1][i] = -1; } else { ancestors[d + 1][i] = ancestors[d][t]; } } } } void dfs(int v, int p, int d) { parent[v] = p; depth[v] = d; for (const int t : tree[v]) { if (t == p) { continue; } dfs(t, v, d + 1); } } int lca(int a, int b) { int da = depth[a], db = depth[b]; if (da > db) { std::swap(a, b); std::swap(da, db); } for (int d = logn; d >= 0; --d) { if (db - (1 << d) >= da) { b = ancestors[d][b]; db -= (1 << d); } } assert(da == db); if (a == b) { return a; } for (int d = logn; d >= 0; --d) { int na = ancestors[d][a]; int nb = ancestors[d][b]; if (na != nb) { a = na; b = nb; } } return parent[a]; } }; void merge(std::set<int> &a, std::set<int> &b) { if (a.size() < b.size()) { std::swap(a, b); } for (const int e : b) { a.insert(e); } } int main() { int N, M, K; std::cin >> N >> M >> K; std::vector<int> A(N - 1), B(N - 1); std::vector<std::vector<int>> tree(N); std::map<std::pair<int, int>, int> edge_id; for (int i = 0; i < N - 1; ++i) { std::cin >> A[i] >> B[i]; tree[--A[i]].push_back(--B[i]); tree[B[i]].push_back(A[i]); edge_id[{A[i], B[i]}] = edge_id[{B[i], A[i]}] = i; } std::vector<int> S(M); std::vector<std::vector<int>> L(M); for (int i = 0; i < M; ++i) { std::cin >> S[i]; L[i].resize(S[i]); for (auto &e : L[i]) { std::cin >> e; --e; } } LCA tree_d(tree); std::vector<std::vector<int>> add_list(N), erase_list(N); for (int i = 0; i < M; ++i) { for (const int e : L[i]) { add_list[e].push_back(i); } int lca = L[i][0]; for (int j = 1; j < S[i]; ++j) { lca = tree_d.lca(lca, L[i][j]); } erase_list[lca].push_back(i); } std::vector<int> answer; auto dfs = [&](auto &&self, const int v, const int p) -> std::set<int> { std::set<int> ls; for (const int t : tree[v]) { if (p == t) { continue; } auto res = self(self, t, v); if ((int)res.size() >= K) { answer.push_back(edge_id[{t, v}]); } merge(ls, res); } for (const int e : add_list[v]) { ls.insert(e); } for (const int e : erase_list[v]) { ls.erase(e); } return ls; }; dfs(dfs, 0, -1); std::sort(answer.begin(), answer.end()); std::cout << answer.size() << std::endl; for (int i = 0; i < (int)answer.size(); ++i) { std::cout << answer[i] + 1 << (i == (int)answer.size() - 1 ? '\n' : ' '); } }
#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...