#include using namespace std; using ll = long long; using ld = long double; #define print(x) cerr << #x << " = " << x << endl template ostream& operator<<(ostream &out, vector &cont) { out << "["; for (const auto &x : cont) out << x << ", "; out << "]"; return out; } int N, K = 25; vector> adj; vector> jumps; vector tin, tout; bool is_ancestor(int u, int v) { return (tin[u] <= tin[v] && tout[u] >= tout[v]); } int dfs1(int u, int p, int time) { if (p != -1) jumps[u][0] = p; for (int i = 1; i < K; i++) { int w = jumpts[u][i - 1]; jumps[u][i] = jumps[w][i - 1]; } for (int v : adj[u]) { if (v != p) { time = dfs(v, u, time + 1) + 1; } } return time; } // return distance from v int lca_dist(int u, int v) { int dist = 0; for (int i = K - 1; i >= 0; i--) { int w = jumps[v][i]; if (is_ancestor(w, v) && is_ancestor(w, u)) { dist += (1 << i); v = w; } } return dist; } int kth_anc(int u, int k) { bitset<32> bs = k; for (int i = K - 1; i >= 0; i--) { if (bs[i]) { u = jumps[u][i]; } } return u; } int ans = 0; vector> a; set zobrane; int dfs2(int u, int p) { if (needed) ans++; for (int v : adj[u]) { if (v != p) { dfs2(v, u); } } bool needed = false; for (int x : a[u]) { if (zobrane.find(x) != find.end()) { zobrane.insert(x); } else { needed = true; } } } int32_t main() { int Q; cin >> N >> Q; adj.assign(N, {}); jumps.assign(N, vector(K, 0)); tin.assign(N, -1); tout.assign(N, -1); a.assign(N, {}); zobrane = {}; ans = 0; for (int i = 0; i < N - 1; i++) { int u, v; cin >> u >> v; adj[u].push_back(v); adj[v].push_back(u); } dfs1(u, u, 0); for (int i = 0; i < Q; i++) { int u, v; cin >> u >> v; int vdist = lca_dist(u, v); int udist = lca_dist(v, u); int dist = udist + vdist; if (udist > vdist) { } else { swap(u, v); } int x = kth_anc(u, dist / 2); int y = x; if (dist % 2 == 1) { y = kth_anc(u, (dist + 1) / 2); } a[x].insert(i); if (x != y) a[y].insert(i); } dfs2(u, u); cout << ans << endl; }