Most tree algorithms want a root. Pick any vertex (or a center when canonicity matters) and DFS.
vector<int> par, depth, sz;vector<vector<int>> adj;void dfs(int u, int p) { par[u] = p; sz[u] = 1; for (int v : adj[u]) { if (v == p) continue; depth[v] = depth[u] + 1; dfs(v, u); sz[u] += sz[v]; }}
par, depth and sz are the three arrays nearly every tree algorithm starts from.
Recursion depth
A path-shaped tree with n=2⋅105 will overflow the default stack on some judges. Either write the DFS iteratively or use an explicit stack:
vector<int> order; order.reserve(n);stack<pair<int,int>> st; st.push({root, -1});while (!st.empty()) { auto [u,p] = st.top(); st.pop(); par[u]=p; order.push_back(u); for (int v : adj[u]) if (v != p) { depth[v]=depth[u]+1; st.push({v,u}); } }for (int i = order.size()-1; i >= 0; i--) { int u = order[i]; sz[u]=1; for (int v : adj[u]) if (v != par[u]) sz[u] += sz[v]; }
Processing order in reverse is a clean way to do “on the way back up” work without recursion.