Description
In the figure, each node is labeled with an integer from {1, 2,...,16}. Node 8 is the root of the tree. Node x is an ancestor of node y if node x is in the path between the root and node y. For example, node 4 is an ancestor of node 16. Node 10 is also an ancestor of node 16. As a matter of fact, nodes 8, 4, 10, and 16 are the ancestors of node 16. Remember that a node is an ancestor of itself. Nodes 8, 4, 6, and 7 are the ancestors of node 7. A node x is called a common ancestor of two different nodes y and z if node x is an ancestor of node y and an ancestor of node z. Thus, nodes 8 and 4 are the common ancestors of nodes 16 and 7. A node x is called the nearest common ancestor of nodes y and z if x is a common ancestor of y and z and nearest to y and z among their common ancestors. Hence, the nearest common ancestor of nodes 16 and 7 is node 4. Node 4 is nearer to nodes 16 and 7 than node 8 is.
For other examples, the nearest common ancestor of nodes 2 and 3 is node 10, the nearest common ancestor of nodes 6 and 13 is node 8, and the nearest common ancestor of nodes 4 and 12 is node 4. In the last example, if y is an ancestor of z, then the nearest common ancestor of y and z is y.
Write a program that finds the nearest common ancestor of two distinct nodes in a tree.
Input
Output
Sample Input
2 16 1 14 8 5 10 16 5 9 4 6 8 4 4 10 1 13 6 15 10 11 6 7 10 2 16 3 8 1 16 12 16 7 5 2 3 3 4 3 1 1 5 3 5
Sample Output
4 3
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<limits.h> #include<vector> typedef long long LL; using namespace std; #define REPF( i , a , b ) for ( int i = a ; i <= b ; ++ i ) #define REP( i , n ) for ( int i = 0 ; i < n ; ++ i ) #define CLEAR( a , x ) memset ( a , x , sizeof a ) const int maxn=10005; int n,uu,vv; vector<int>v[maxn]; int pre[maxn],vis[maxn]; bool root[maxn]; int find_root(int x) { if(pre[x]!=x) x=find_root(pre[x]); return pre[x]; } void Union(int x,int y) { x=find_root(x); y=find_root(y); if(x!=y) pre[y]=x; } void LCA(int x) { for(int i=0;i<v[x].size();i++) { LCA(v[x][i]); Union(x,v[x][i]); } vis[x]=1; if(x==uu&&vis[vv]==1) { printf("%d\n",find_root(vv)); return ; } if(x==vv&&vis[uu]==1) { printf("%d\n",find_root(uu)); return ; } } void init() { REP(i,maxn) { v[i].clear(); pre[i]=i; root[i]=true; vis[i]=0; } } void solve() { REPF(i,1,n) { if(root[i]==true) { LCA(i); break; } } // for(int i=1;i<=n;i++) // printf("222222 %d\n",pre[i]); } int main() { int t,a,b; scanf("%d",&t); while(t--) { scanf("%d",&n); init(); REPF(i,1,n-1) { scanf("%d%d",&a,&b); v[a].push_back(b); root[b]=false; } scanf("%d%d",&uu,&vv); solve(); } return 0; }