Submission #1143831

#TimeUsernameProblemLanguageResultExecution timeMemory
1143831monkey133Unique Cities (JOI19_ho_t5)C++20
0 / 100
214 ms43140 KiB
#include <bits/stdc++.h> using namespace std; // --- GLOBAL DATA STRUCTURES --- // We use 1-indexing for the cities. int N, M; vector<vector<int>> adj; // tree: for each city, its adjacent cities vector<int> speciality; // speciality[i] is the speciality produced at city i // --- MEMOIZATION FOR THE "CHAIN" (directed edge) --- // For each directed edge (x -> u), we want to store the chain (as a vector<int>) // defined by: // f(x,u)[1] = u, // and if (u, v) is the unique continuation (i.e. among u’s neighbors excluding x, if there is exactly one neighbor v) // then for d>=2: f(x,u)[d] = f(u,v)[d-1], // otherwise the chain stops. // We use a key for a directed edge. struct EdgeKey { int u, v; // u -> v (starting at u then going to v) bool operator==(const EdgeKey &other) const { return u == other.u && v == other.v; } }; struct EdgeKeyHash { std::size_t operator()(const EdgeKey &ek) const { return ((size_t)ek.u) * 100007ULL + ek.v; } }; // memo: maps the directed edge (x -> u) to the chain vector. unordered_map<EdgeKey, vector<int>, EdgeKeyHash> memo; // Recursive function: getChain(x,u) returns the chain (as a vector<int>) for the directed edge x->u. vector<int> getChain(int x, int u) { EdgeKey key = {x, u}; if(memo.find(key) != memo.end()) return memo[key]; vector<int> chain; // The first city in the chain is u (at distance 1 from x). chain.push_back(u); // Now, see if we can extend the chain. // Look at u’s neighbors except x. int cnt = 0; int next = -1; for (int w : adj[u]) { if (w == x) continue; cnt++; next = w; } // If there is exactly one neighbor (i.e. the branch is a chain) then extend. if (cnt == 1) { vector<int> rest = getChain(u, next); chain.insert(chain.end(), rest.begin(), rest.end()); } memo[key] = chain; return chain; } // --- MAIN --- int main(){ ios::sync_with_stdio(false); cin.tie(nullptr); cin >> N; // Read the tree adj.assign(N+1, vector<int>()); for (int i=1; i<=N-1; i++){ int A, B; cin >> A >> B; adj[A].push_back(B); adj[B].push_back(A); } cin >> M; // Read the speciality produced at each city. // (Cities are numbered 1..N.) speciality.resize(N+1); for (int i=1; i<=N; i++){ cin >> speciality[i]; } // ans[x] will store the answer for city x. vector<int> ans(N+1, 0); // Process each city x. // For city x, the idea is: // - For every neighbor u of x, compute L(x,u) = (length of the chain from x->u) // - If x is a leaf (degree 1), then the unique branch is the only branch and unique distances are 1..L(x,u). // - Otherwise, let L1 = maximum chain length among neighbors, // and let L2 = the second maximum (or 0 if x has only one neighbor). // Then if the maximum L1 is unique (i.e. only one neighbor attains L1) the unique distances are // d = L2+1, L2+2, …, L1. // - Finally, “read off” the cities at these distances from the chain that gave L1 and count distinct specialities. for (int x = 1; x <= N; x++){ int deg = adj[x].size(); if(deg == 0) { // should not happen in a connected tree ans[x] = 0; continue; } // branchInfo: for each neighbor u of x, store pair {chain length, neighbor u} vector<pair<int,int>> branchInfo; for (int u : adj[x]){ vector<int> chain = getChain(x, u); int len = chain.size(); // note: len is the maximum distance from x along branch u branchInfo.push_back({len, u}); } if(deg == 1){ // Only one branch. Then unique distances are 1..L, where L = chain length. int L1 = branchInfo[0].first; vector<int> chain = getChain(x, branchInfo[0].second); unordered_set<int> specSet; // d=1 corresponds to chain[0], d=2 to chain[1], …, d=L1 to chain[L1-1]. for (int d = 1; d <= L1; d++){ specSet.insert(speciality[ chain[d-1] ]); } ans[x] = specSet.size(); } else { // x has at least two neighbors. int L1 = -1, L2 = -1; int countMax = 0; // count how many branches attain the maximum length L1. int bestNeighbor = -1; for (auto &p : branchInfo){ int L = p.first; if(L > L1){ L2 = L1; L1 = L; bestNeighbor = p.second; countMax = 1; } else if(L == L1){ countMax++; } else if(L > L2){ L2 = L; } } // If the maximum chain length appears at least twice then no distance d has S_x(d)==1. if(countMax != 1){ ans[x] = 0; } else { // Unique distances for x are d = L2+1, L2+2, …, L1. vector<int> chain = getChain(x, bestNeighbor); unordered_set<int> specSet; // d (1-indexed) means chain index (d-1). for (int d = L2+1; d <= L1; d++){ specSet.insert(speciality[ chain[d-1] ]); } ans[x] = specSet.size(); } } } // Output the answer for each city. for (int i=1; i<=N; i++){ cout << ans[i] << "\n"; } return 0; }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...