#include #include #include using namespace std; vector depth, parent, checklca, L, E, H ; vector> adj ; vector> nontree, check ; using namespace std; // from Competitive Programming 4 by Halim, Halim, Effendy typedef vector vi; class SparseTable { // OOP style private: vi A, P2, L2; vector SpT; // the Sparse Table public: SparseTable() {} // default constructor SparseTable(vi &initialA) { // pre-processing routine A = initialA; int n = (int)A.size(); int L2_n = (int)log2(n)+1; P2.assign(L2_n+1, 0); L2.assign(2<(L2[n]+1, vi(n)); for (int j = 0; j < n; ++j) SpT[0][j] = j; // RMQ of sub array [j..j] // the two nested loops below have overall time complexity = O(n log n) for (int i = 1; P2[i] <= n; ++i) // for all i s.t. 2^i <= n for (int j = 0; j+P2[i]-1 < n; ++j) { // for all valid j int x = SpT[i-1][j]; // [j..j+2^(i-1)-1] int y = SpT[i-1][j+P2[i-1]]; // [j+2^(i-1)..j+2^i-1] SpT[i][j] = A[x] <= A[y] ? x : y; } } int RMQ(int i, int j) const { int k = L2[j-i+1]; // 2^k <= (j-i+1) int x = SpT[k][i]; // covers [i..i+2^k-1] int y = SpT[k][j-P2[k]+1]; // covers [j-2^k+1..j] return A[x] <= A[y] ? x : y; } }; void dfs(int cur, int depth) { H[cur] = E.size() ; E.push_back(cur) ; L.push_back(depth) ; for (auto nxt: adj[cur]) if (parent[nxt] == cur) { dfs(nxt, depth+1) ; E.push_back(cur) ; L.push_back(depth) ; } } void dfs(int a) { for (int i=0; i<(int)adj[a].size(); i++) { int b = adj[a][i]; if (parent[b] == a) { dfs(b) ; } else if (parent[a] != b) { nontree.push_back({a,b}) ; swap(adj[a][i], adj[a][adj[a].size()-1]) ; adj[a].pop_back() ; i-- ; } } } int lca(const SparseTable &st, int a, int b) { if (a == b) return a ; if (H[a] > H[b]) swap(a, b) ; return E[st.RMQ(H[a], H[b])] ; } int intsct(const SparseTable &st, int a, int b, int ab, int c, int d, int cd) { int abcd = lca(st, ab, cd) ; return (abcd == cd && (lca(st, ab, c) == ab || lca(st, ab, d) == ab)) || (abcd == ab && (lca(st, cd, a) == cd || lca(st, cd, b) == cd)) ; } int npaths(const SparseTable &st, int a, int b) ; int tryto(const SparseTable &st, int a, int b, int c, int d) { int ab = lca(st, a, b) ; for (int i=0; i+1<(int)check.size(); i++) if (intsct(st, a, b, ab, check[i].first, check[i].second, checklca[i])) return 0 ; return npaths(st, c, d) ; } int npaths(const SparseTable &st, int a, int b) { if (a < 0) return 1 ; int r = 0 ; for (auto p: nontree) { check.push_back({a,p.first}) ; checklca.push_back(lca(st, a,p.first)) ; r += tryto(st, a, p.first, p.second, b) ; checklca.pop_back() ; check.pop_back() ; } return r ; } int main(int argc, char const *argv[]) { int n, nq ; cin >> n >> nq ; adj.resize(n) ; for (int i=0; i> a >> b ; a-- ; b-- ; adj[a].push_back(b) ; adj[b].push_back(a) ; } depth.resize(n) ; vector q ; depth[0] = 1 ; q.push_back(0) ; parent.resize(n) ; for (int qg=0; qg<(int)q.size(); qg++) { int a = q[qg] ; for (auto b: adj[a]) if (depth[b] == 0) { parent[b] = a ; depth[b] = depth[a] + 1 ; q.push_back(b) ; } } dfs(0) ; H.resize(n, -1) ; dfs(0, 0) ; SparseTable st(L) ; nontree.push_back({-1, -1}) ; for (int i=0; i> a >> b ; nontree[nontree.size()-1].first = b-1 ; cout << npaths(st, a-1, b-1) << endl ; } }