Submission #827646

#TimeUsernameProblemLanguageResultExecution timeMemory
827646happypotatoMergers (JOI19_mergers)C++17
100 / 100
885 ms136704 KiB
#include <bits/stdc++.h> using namespace std; #define pii pair<int, int> #define ff first #define ss second #define pb push_back const int mxN = 5e5 + 1; vector<int> adj[mxN]; int a[mxN]; vector<int> state[mxN]; int n, k; void Input() { cin >> n >> k; for (int i = 0; i < n - 1; i++) { int u, v; cin >> u >> v; adj[u].pb(v); adj[v].pb(u); } for (int i = 1; i <= n; i++) { cin >> a[i]; state[a[i]].pb(i); } } int tt = 0; int dep[mxN]; pii range[mxN]; int lift[mxN][20]; void dfs1(int u = 1, int par = 0, int depth = 1) { dep[u] = depth; range[u].ff = ++tt; lift[u][0] = par; for (int &v : adj[u]) { if (v == par) continue; dfs1(v, u, depth + 1); } range[u].ss = tt; } void BuildLift() { for (int bit = 1; bit < 20; bit++) { for (int i = 1; i <= n; i++) { lift[i][bit] = lift[lift[i][bit - 1]][bit - 1]; } } } int FindLCA(int u, int v) { if (dep[u] > dep[v]) swap(u, v); int diff = dep[v] - dep[u]; for (int i = 19; i >= 0; i--) { if (diff & (1 << i)) { v = lift[v][i]; } } if (u == v) return u; for (int i = 19; i >= 0; i--) { if (lift[u][i] != lift[v][i]) { u = lift[u][i]; v = lift[v][i]; } } return lift[u][0]; } bool cmp(int &x, int &y) { return range[x].ff < range[y].ff; } int dp[mxN]; void dfs2(int u = 1, int par = 0) { for (int &v : adj[u]) { if (v == par) continue; dfs2(v, u); dp[u] += dp[v]; } } int dsupp[mxN]; int DSUFind(int u) { if (dsupp[u] == 0) return u; return (dsupp[u] = DSUFind(dsupp[u])); } void DSUMerge(int u, int v) { u = DSUFind(u); v = DSUFind(v); if (u != v) dsupp[v] = u; } int deg[mxN]; void solve() { Input(); dfs1(); BuildLift(); for (int i = 1; i <= k; i++) { sort(state[i].begin(), state[i].end(), cmp); for (int j = 1; j < (int)(state[i].size()); j++) { int u = state[i][j - 1], v = state[i][j]; int lca = FindLCA(u, v); // colour edges from u to lca and from v to lca dp[u]++; dp[lca]--; dp[v]++; dp[lca]--; } } dfs2(); for (int i = 2; i <= n; i++) { if (dp[i] > 0) { DSUMerge(i, lift[i][0]); } } // find degree of tree after merging for (int i = 2; i <= n; i++) { if (dp[i] == 0) { deg[DSUFind(i)]++; deg[DSUFind(lift[i][0])]++; } } int leaves = 0; for (int i = 1; i <= n; i++) { leaves += (deg[i] == 1); } cout << (leaves + 1) / 2 << endl; } int32_t main() { ios::sync_with_stdio(0); cin.tie(0); solve(); }
#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...