Submission #1125100

#TimeUsernameProblemLanguageResultExecution timeMemory
1125100PanndaUsmjeri (COCI17_usmjeri)C++20
140 / 140
257 ms60124 KiB
#include <bits/stdc++.h> using namespace std; struct Tree { vector<int> depth, parent, siz, head, begin, end, inv_begin; Tree(const int &n, const vector<vector<int>> &adj, int root = 0) : depth(n), parent(n), siz(n), head(n), begin(n), end(n), inv_begin(n) { auto dfs = [&](auto self, int u, int p) -> void { depth[u] = p == -1 ? 0 : depth[p] + 1; parent[u] = p; siz[u] = 1; for (int v : adj[u]) { if (v == p) continue; self(self, v, u); siz[u] += siz[v]; } }; dfs(dfs, root, -1); int tim = 0; auto decompose = [&](auto self, int u, int h) -> void { head[u] = h; int heavy = -1; begin[u] = tim++; inv_begin[begin[u]] = u; for (int v : adj[u]) { if (v == parent[u]) continue; if (heavy == -1 || siz[v] > siz[heavy]) heavy = v; } if (heavy != -1) self(self, heavy, h); for (int v : adj[u]) { if (v == parent[u] || v == heavy) continue; self(self, v, v); } end[u] = tim; }; decompose(decompose, root, root); } int getDepth(int u) { return depth[u]; } int getParent(int u) { return parent[u]; } int getAncestor(int u, int k) { // returns the kth ancestor of u, -1 if out of tree. For example: 0th is u, 1st is parent(u),... while (k > 0 && u != -1) { if (k > depth[u] - depth[head[u]]) { k -= depth[u] - depth[head[u]] + 1; u = parent[head[u]]; } else { u = inv_begin[begin[u] - k]; k = 0; } } return u; } bool isDescendant(int upper, int lower) { return begin[upper] <= begin[lower] && begin[lower] < end[upper]; } bool isProperDescendant(int upper, int lower) { return begin[upper] < begin[lower] && begin[lower] < end[upper]; } int getLCA(int u, int v) { for (; head[u] != head[v]; v = parent[head[v]]) { if (depth[head[u]] > depth[head[v]]) swap(u, v); } if (depth[u] > depth[v]) swap(u, v); return u; } int getDist(int u, int v) { return depth[u] + depth[v] - 2 * depth[getLCA(u, v)]; } int getIntermediate(int heavy, int u) { // returns the first node that isn't 'heavy' on the path from 'heavy' to 'u' assert(heavy != u); if (heavy != getLCA(u, heavy)) { return parent[heavy]; } while (head[u] != head[heavy]) { u = head[u]; if (parent[u] == heavy) return u; u = parent[u]; } return inv_begin[begin[heavy] + 1]; } int getNode(int u) { // maps nodes -> positions in the Euler tour return begin[u]; } int getInvNode(int p) { // maps Euler tour positions -> nodes return inv_begin[p]; } array<int, 2> getSubtree(int u) { // returns the subtree rooted at u, presented by the range of positions in the Euler tour return array<int, 2>{ begin[u], end[u] }; } vector<array<int, 2>> getPath(int u, int v) { // returns the path [u, v], presented by a list of O(log) ranges that are the positions in the Euler tour vector<array<int, 2>> res; for (; head[u] != head[v]; v = parent[head[v]]) { if (depth[head[u]] > depth[head[v]]) swap(u, v); res.push_back({ begin[head[v]], begin[v] + 1 }); } if (depth[u] > depth[v]) swap(u, v); res.push_back({ begin[u], begin[v] + 1 }); return res; } pair<vector<int>, vector<array<int, 2>>> virtualTree(vector<int> nodes) { // returns a pair: the list of nodes in the virtual tree (at most 2*|nodes|), and the list of edges of that virtual tree sort(nodes.begin(), nodes.end(), [&](int u, int v) { return begin[u] < begin[v]; }); int siz = nodes.size(); for (int i = 0; i + 1 < siz; i++) { nodes.push_back(getLCA(nodes[i], nodes[i + 1])); } sort(nodes.begin(), nodes.end(), [&](int u, int v) { return begin[u] < begin[v]; }); nodes.resize(unique(nodes.begin(), nodes.end()) - nodes.begin()); vector<array<int, 2>> edges; vector<int> stk; for (int u : nodes) { while (!stk.empty() && !isProperDescendant(stk.back(), u)) { stk.pop_back(); } if (!stk.empty()) { edges.push_back({stk.back(), u}); } stk.push_back(u); } return {nodes, edges}; } }; struct DSU { int n; vector<int> f; DSU(int n) : n(n), f(n) { iota(f.begin(), f.end(), 0); } int leader(int u) { while (u != f[u]) { u = f[u] = f[f[u]]; } return u; } bool unionize(int u, int v) { u = leader(u); v = leader(v); if (u == v) return false; f[u] = v; n--; return true; } bool same(int u, int v) { return leader(u) == leader(v); } int count() { return n; } }; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int n, m; cin >> n >> m; vector<vector<int>> adj(n); for (int i = 0; i < n - 1; i++) { int u, v; cin >> u >> v; u--; v--; adj[u].push_back(v); adj[v].push_back(u); } Tree tree(n, adj); DSU dsu(n); vector<int> f(n, 1); vector<array<int, 2>> notes; for (int i = 0; i < m; i++) { int u, v; cin >> u >> v; u--; v--; int uv = tree.getLCA(u, v); f[u] = max(f[u], tree.getDepth(u) - tree.getDepth(uv)); f[v] = max(f[v], tree.getDepth(v) - tree.getDepth(uv)); if (uv != u && uv != v) { notes.push_back({tree.getIntermediate(uv, u), tree.getIntermediate(uv, v)}); } } auto dfs = [&](auto self, int u, int p) -> void { for (int v : adj[u]) { if (v == p) continue; self(self, v, u); if (u == 0) continue; if (f[v] > 1) dsu.unionize(v, u); f[u] = max(f[u], f[v] - 1); } }; dfs(dfs, 0, -1); for (auto [u, v] : notes) { if (dsu.same(u, v)) { cout << 0 << '\n'; return 0; } } for (auto [u, v] : notes) { dsu.unionize(u, v); } int ans = 1; for (int i = dsu.count() - 1; i > 0; i--) { ans = 2 * ans % ((int)1e9 + 7); } cout << ans << '\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...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...