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
题意:n组数据,y-1条边,最后一个求lca;我的代码思路根据最后的在线算法得出;


#include<iostream> #include<cstdio> #include<cmath> #include<string> #include<queue> #include<algorithm> #include<stack> #include<cstring> #include<vector> #include<list> #include<set> #include<map> using namespace std; #define ll long long #define mod 1000000007 #define inf 999999999 //#pragma comment(linker, "/STACK:102400000,102400000") int scan() { int res = 0 , ch ; while( !( ( ch = getchar() ) >= '0' && ch <= '9' ) ) { if( ch == EOF ) return 1 << 30 ; } res = ch - '0' ; while( ( ch = getchar() ) >= '0' && ch <= '9' ) res = res * 10 + ( ch - '0' ) ; return res ; } struct is { int u,v; int next; }edge[20010]; int head[20010]; int deep[20010]; int rudu[20100]; int first[20010]; int dfn[20010];//存深搜的数组 int dp[20010][30]; int point,jiedge; int minn(int x,int y) { return deep[x]<=deep[y]?x:y; } void update(int u,int v) { jiedge++; edge[jiedge].u=u; edge[jiedge].v=v; edge[jiedge].next=head[u]; head[u]=jiedge; } void dfs(int u,int step) { dfn[++point]=u; deep[point]=step; if(!first[u]) first[u]=point; for(int i=head[u];i;i=edge[i].next) { int v=edge[i].v; dfs(v,step+1); dfn[++point]=u; deep[point]=step; } } void st(int len) { for(int i=1;i<=len;i++) dp[i][0]=i; for(int j=1;(1<<j)<=len;j++) for(int i=1;i+(1<<j)-1<=len;i++) { dp[i][j]=minn(dp[i][j-1],dp[i+(1<<(j-1))][j-1]); } } int query(int l,int r) { int lll=first[l]; int rr=first[r]; if(lll>rr) swap(lll,rr); int x=(int)(log((double)(rr-lll+1))/log(2.0)); return dfn[minn(dp[lll][x],dp[rr-(1<<x)+1][x])]; } int main() { int x,y,z,i,t; scanf("%d",&x); while(x--) { memset(head,0,sizeof(head)); memset(rudu,0,sizeof(rudu)); memset(first,0,sizeof(first)); point=0; jiedge=0; scanf("%d",&y); for(i=1;i<y;i++) { int u,v; scanf("%d%d",&u,&v); update(u,v); rudu[v]++; } for(i=1;i<=y;i++) if(!rudu[i]) { dfs(i,0); break; } st(point); int u,v; scanf("%d%d",&u,&v); printf("%d\n",query(u,v)); } return 0; }