#include #include #include #include #include #include using namespace std; template class y_combinator_result { Fun fun_; public: template explicit y_combinator_result(T &&fun): fun_(std::forward(fun)) {} template decltype(auto) operator()(Args &&...args) { return fun_(std::ref(*this), std::forward(args)...); } }; template decltype(auto) y_combinator(Fun &&fun) { return y_combinator_result>(std::forward(fun)); } struct disjoint_set { vector p; disjoint_set(int n) { p.assign(n, -1); } int find(int x) { if (p[x] < 0) return x; return p[x] = find(p[x]); } bool merge(int x, int y) { x = find(x); y = find(y); if(x == y) return false; p[x] = y; return true; } }; struct LCA { vector depth; vector> anc; int n; int d; vector startt, treesz; LCA(const vector>& tree) { auto dfs = y_combinator([&](auto self, int curr, int par, int& id) -> void { startt[curr] = id++; for(int out: tree[curr]) { if(out == par) continue; anc[out][0] = curr; depth[out] = depth[curr] + 1; self(out, curr, id); treesz[curr] += treesz[out]; } }); n = tree.size(); startt.assign(n, -1); treesz.assign(n, 1); depth.assign(n, 1e9); depth[0] = 0; d = 1; while((1<= 0; k--) { if(depth[a] - depth[b] >= (1 << k)) a = anc[a][k]; } assert(depth[a] == depth[b]); for(int k = d-1; k >= 0; k--) { if(anc[a][k] != anc[b][k]) { a = anc[a][k]; b = anc[b][k]; } } if(a != b) { return anc[a][0]; } return a; } bool onPath(int x, int lhs, int rhs) { if(depth[lhs] > depth[rhs]) swap(lhs, rhs); return startt[lhs] <= startt[x] && startt[x] < startt[lhs] + treesz[lhs] && startt[x] <= startt[rhs] && startt[rhs] < startt[x] + treesz[x]; } bool overlap(int a, int b, int c, int d) { int lhs = getLCA(a, b); int rhs = getLCA(c, d); return onPath(lhs, c, rhs) || onPath(lhs, d, rhs) || onPath(rhs, a, lhs) || onPath(rhs, lhs, b); } }; int main() { int n, q; cin >> n >> q; vector> extra; disjoint_set dsu(n); vector> tree(n); for(int i = 0; i < n+1; i++) { int a, b; cin >> a >> b; if(dsu.merge(--a, --b)) { tree[a].push_back(b); tree[b].push_back(a); } else extra.push_back({a, b}); } assert(extra.size() == 2); LCA lca(tree); while(q--) { int x, y; cin >> x >> y; x--; y--; int ret = 1; for(int i = 0; i < 2; i++) { ret += !lca.overlap(x, extra[i][0], extra[i][1], y); ret += !lca.overlap(x, extra[i][1], extra[i][0], y); } for(int i = 0; i < 2; i++) { for(int a = 0; a < 2; a++) for(int b = 0; b < 2; b++) { vector vertices; vertices.push_back(x); vertices.push_back(extra[i][a]); vertices.push_back(extra[i][a^1]); vertices.push_back(extra[i^1][b]); vertices.push_back(extra[i^1][b^1]); vertices.push_back(y); bool good = true; good = good && !lca.overlap(vertices[0], vertices[1], vertices[2], vertices[3]); good = good && !lca.overlap(vertices[0], vertices[1], vertices[4], vertices[5]); good = good && !lca.overlap(vertices[2], vertices[3], vertices[4], vertices[5]); ret += good; } } cout << ret << "\n"; } }