經典LCA操做。。java
貼AC代碼code
import java.lang.reflect.Array; import java.util.*; public class POJ1330 { // 並查集部分 static int[] p; static int find(int u){ if(p[u]!=u){ p[u] = find(p[u]); } return p[u]; } static class Edge{ int to; int next; } // 鏈式前向星 static int[] head; static Edge[] edges; static boolean[] vist; // 所求LCA的兩點 static int qfrom; static int qto; // 找根 static boolean[] isroot; static boolean LCA(int u){ // 在以本身爲根的子樹中計算LCA // 若是沒找到就回溯到父節點,再向下去兄弟子樹計算 // 先創建以本身爲表明的並查集 p[u]=u; vist[u]=true; for(int k=head[u];k>=0;k=edges[k].next){ int to = edges[k].to; if(!vist[to]) { // 計算子樹 // 若是在某棵子樹計算過程當中算出結果,就返回true if(LCA(to)) return true; // 子樹計算完,把子樹的並查集表明節點設爲當前節點 p[to] = u; } } // 全部子樹計算完畢,還沒發現結果 // 試試用當前節點計算結果 if(u == qfrom){ if(vist[qto]){ System.out.println(find(qto)); return true; } }else if(u==qto){ if(vist[qfrom]){ System.out.println(find(qfrom)); return true; } } // 仍是沒算出結果,向上回溯,準備去兄弟子樹計算 return false; } public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); while (n-- > 0){ int m = sc.nextInt(); p = new int[m+1]; head = new int[m+1]; Arrays.fill(head,-1); edges = new Edge[m]; vist = new boolean[m+1]; isroot = new boolean[m+1]; Arrays.fill(isroot,true); // 鏈式前向星構有向圖 for(int i=0;i<m-1;i++){ int from = sc.nextInt(); int to = sc.nextInt(); Edge edge = new Edge(); edge.to=to; edge.next=head[from]; edges[i]=edge; head[from]=i; // 有父節點的不是根 isroot[to]=false; } qfrom = sc.nextInt(); qto = sc.nextInt(); // 找根 int root=0; for(int i=1;i<isroot.length;i++){ if(isroot[i]) { root = i; break; } } // 計算LCA LCA(root); } } }