Submission #1215740

#TimeUsernameProblemLanguageResultExecution timeMemory
1215740madamadam3Network (BOI15_net)C++20
0 / 100
0 ms324 KiB
/********************************************************************** * Read a 1-indexed tree, find a centroid, root there, * * hash the tree “( … child-hashes … )” style (lexicographically * * sorting the hashes), then perform a second DFS that always visits * * the child with the smallest hash first. The second DFS records * * tin / tout / depth arrays and collects all leaves in the order * * they are first encountered. * **********************************************************************/ #include <bits/stdc++.h> using namespace std; struct TreeHasher { int n; // number of vertices vector<vector<int>> g; // 1-indexed adjacency list vector<int> sz; // subtree sizes int centroid; // chosen centroid vector<string> h; // hash of subtree rooted at v vector<int> tin, tout, depth; // euler timestamps & depths vector<int> eulerLeaves; // leaves in visit order int timer = 0; explicit TreeHasher(int N) : n(N) { g.assign(n + 1, {}); sz.assign(n + 1, 0); h.assign(n + 1, ""); tin.assign(n + 1, 0); tout.assign(n + 1, 0); depth.assign(n + 1, 0); } /*----------------------------------------------------------------*/ /* 1. centroid (classic single pass) */ /*----------------------------------------------------------------*/ void dfsSz(int u, int p) { sz[u] = 1; bool isCentroid = true; for (int v : g[u]) if (v != p) { dfsSz(v, u); sz[u] += sz[v]; if (sz[v] * 2 > n) isCentroid = false; } if ((n - sz[u]) * 2 > n) isCentroid = false; if (isCentroid) centroid = u; } /*----------------------------------------------------------------*/ /* 2. subtree hash (“canonical form” of unordered rooted tree) */ /*----------------------------------------------------------------*/ string dfsHash(int u, int p) { vector<string> childHashes; for (int v : g[u]) if (v != p) childHashes.push_back(dfsHash(v, u)); sort(childHashes.begin(), childHashes.end()); string cur = "("; for (auto& s : childHashes) cur += s; cur += ")"; return h[u] = cur; } /*----------------------------------------------------------------*/ /* 3. stable-order DFS: children visited in ascending hash order */ /*----------------------------------------------------------------*/ void dfsOrder(int u, int p) { tin[u] = ++timer; bool isLeaf = (u != centroid && g[u].size() == 1); if (isLeaf) eulerLeaves.push_back(u); // collect & sort children by their already-computed hashes vector<int> children; for (int v : g[u]) if (v != p) children.push_back(v); sort(children.begin(), children.end(), [&](int a, int b) { return h[a] < h[b]; }); for (int v : children) { depth[v] = depth[u] + 1; dfsOrder(v, u); } tout[u] = ++timer; } /*----------------------------------------------------------------*/ /* Main entry point */ /*----------------------------------------------------------------*/ void process() { dfsSz(1, 0); // pick centroid dfsHash(centroid, 0); // hashes with centroid as root depth[centroid] = 0; dfsOrder(centroid, 0); // stable-order DFS } }; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int n; if (!(cin >> n) || n <= 0) return 0; TreeHasher TH(n); for (int i = 0, u, v; i < n - 1; ++i) { cin >> u >> v; // u++; v++; TH.g[u].push_back(v); TH.g[v].push_back(u); } TH.process(); /*-------------------------------------------------------------*/ /* Example output – adjust / remove as you need */ /*-------------------------------------------------------------*/ // cout << "Centroid: " << TH.centroid << '\n'; // cout << "Global hash: " << TH.h[TH.centroid] << '\n'; // cout << "tin:"; // for (int i = 1; i <= n; ++i) cout << ' ' << TH.tin[i]; // cout << "\ntout:"; // for (int i = 1; i <= n; ++i) cout << ' ' << TH.tout[i]; // cout << "\ndepth:"; // for (int i = 1; i <= n; ++i) cout << ' ' << TH.depth[i]; // cout << '\n'; // cout << "Leaves in visit order:"; // for (int v : TH.eulerLeaves) cout << ' ' << v; // cout << '\n'; deque<int> dd(TH.eulerLeaves.begin(), TH.eulerLeaves.end()); cout << ((TH.eulerLeaves.size() + 1) / 2) << "\n"; cout << dd.front() << " " << dd.back() << "\n"; dd.pop_back(); dd.pop_front(); while (!dd.empty()) { int c1 = dd.front(); dd.pop_front(); int c2 = dd.front(); dd.pop_front(); cout << c1 << " " << c2 << "\n"; if (dd.size() == 1) { int c3 = dd.front(); dd.pop_front(); cout << c2 << " " << c3 << "\n"; } } }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...