// goodwincommaderek@gmail.com import java.util.ArrayList; import java.util.Arrays; import java.util.Scanner; public class elevatedrails_dg_ac { public static void main(String[] args) { Scanner in = new Scanner(System.in); int N = in.nextInt(); int Q = in.nextInt(); Forest forest = new Forest(N); for (int n = 0; n < N - 3; n++) { int a = in.nextInt() - 1; int b = in.nextInt() - 1; forest.connect(a, b); } // let each node which tree it's in WhichTree whichTree = new WhichTree(forest); // get information about diameters of trees FarthestDists farthestDists = new FarthestDists(forest, whichTree); // don't mind this too much; i just want to cut down on casework int notTrees = 0 ^ 1 ^ 2; StringBuilder sb = new StringBuilder(); for (int q = 0; q != Q; q++) { int a = in.nextInt() - 1; int b = in.nextInt() - 1; // strategy for each query: // force a train to travel to its farthest away node in a, // through the diameter of the tree not of a or b, // and along the farthest possible path to b. int aTree = whichTree.whichTree[a]; int bTree = whichTree.whichTree[b]; int middleTree = notTrees ^ aTree ^ bTree; int ans = farthestDists.dist[a] + 1 + farthestDists.treeDiameter[middleTree] + 1 + farthestDists.dist[b]; ans++; // we want the number of stations, not the number of paths. if (Q < 0) { System.out.println(ans); } else { sb.append(ans).append('\n'); } } System.out.print(sb); } static class FarthestDists { int N; Forest forest; int[] dist; int[] treeDiameter; FarthestDists(Forest forest, WhichTree whichTree) { this.forest = forest; N = forest.adj.length; dist = new int[N]; Arrays.fill(dist, -1); // use the trick which gets haw far away the furthest node is // this uses three DFSs // DFS 1) make each node store its distance from an arbitrary node in the same tree for (int n = 0; n < N; n++) { if (dist[n] == -1) { dfs(n, -1, 0); } } // choose any furthest node in the tree away from the arbitrary node. // this is one diameter endpoint. int[] endpt1 = new int[3]; Arrays.fill(endpt1, -1); for (int n = 0; n < N; n++) { int tree = whichTree.whichTree[n]; if (endpt1[tree] == -1 || dist[endpt1[tree]] < dist[n]) { endpt1[tree] = n; } } // DFS 2) now find the furthest dist away from the arbitrary node. // completely redo dist in the process. for (int t = 0; t < 3; t++) { dfs(endpt1[t], -1, 0); } // find the other endpoint int[] endpt2 = new int[3]; Arrays.fill(endpt2, -1); for (int n = 0; n < N; n++) { int tree = whichTree.whichTree[n]; if (endpt2[tree] == -1 || dist[endpt2[tree]] < dist[n]) { endpt2[tree] = n; } } // DFS 3) now dfs from the other endpoint for (int t = 0; t < 3; t++) { dfsMax(endpt2[t], -1, 0); } // now, dist should represent the farthest node from each node // find the diameter of each tree treeDiameter = new int[3]; Arrays.fill(treeDiameter, 0); for (int n = 0; n < N; n++) { int tree = whichTree.whichTree[n]; if (treeDiameter[tree] < dist[n]) { treeDiameter[tree] = dist[n]; } } } void dfs(int u, int prev, int distFrom) { dist[u] = distFrom; for (Edge e : forest.adj[u]) { int v = e.other(u); if (v != prev) { dfs(v, u, 1 + distFrom); } } } // the only difference between this and normal dfs // is how dist[u] is calculated void dfsMax(int u, int prev, int distFrom) { dist[u] = Math.max(dist[u], distFrom); // the only difference!!! for (Edge e : forest.adj[u]) { int v = e.other(u); if (v != prev) { dfsMax(v, u, 1 + distFrom); // except this } } } } static class WhichTree { int[] whichTree; Forest forest; WhichTree(Forest forest) { this.forest = forest; int N = forest.adj.length; whichTree = new int[N]; Arrays.fill(whichTree, -1); for (int n = 0, tree = 0; n < N; n++) { if (whichTree[n] == -1) { fill(n, -1, tree); tree++; } } } void fill(int u, int prev, int label) { whichTree[u] = label; for (Edge e : forest.adj[u]) { int v = e.other(u); if (v != prev) { fill(v, u, label); } } } } static class Forest { ArrayList[] adj; Forest(int N) { adj = new ArrayList[N]; for (int n = 0; n < N; n++) { adj[n] = new ArrayList<>(2); } } void connect(int a, int b) { Edge e = new Edge(a, b); adj[a].add(e); adj[b].add(e); } } static class Edge { int a, b; Edge(int aa, int bb) { a = aa; b = bb; } int other(int o) { return o ^ a ^ b; } } }