POJ 1330 Nearest Common ancesters(LCA,Tarjan离线算法)

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

The input consists of T test cases. The number of test cases (T) is given in the first line of the input file. Each test case starts with a line containing an integer N , the number of nodes in a tree, 2<=N<=10,000. The nodes are labeled with integers 1, 2,…, N. Each of the next N -1 lines contains a pair of integers that represent an edge –the first integer is the parent node of the second integer. Note that a tree with N nodes has exactly N – 1 edges. The last line of each test case contains two distinct integers whose nearest common ancestor is to be computed.

Output:

Print exactly one line for each test case. The line should contain the integer that is the nearest common ancestor.

Sample Input:

2161 148 510 165 94 68 44 101 136 1510 116 710 216 38 116 1216 752 33 43 11 53 5

Sample output:

4

3

纯模版题,测试模版,留着用。

#include<stdio.h>#include<string.h>#include<iostream>#include<algorithm>#include<math.h>#include<vector>using namespace std;const int MAXN=10010;//树中结点的数目int F[MAXN];//并查集int r[MAXN];//并查集中集合的个数bool vis[MAXN];//访问标记int ancestor[MAXN];//祖先struct Node{int to, next;}edge[MAXN*2];int head[MAXN];int tol;void addedge(int a,int b){edge[tol].to=b;edge[tol].next=head[a];head[a]=tol++;edge[tol].to=a;edge[tol].next=head[b];head[b]=tol++;}struct Query{int q,next;int index;//查询编号}query[MAXN*2];//查询数int ans[MAXN*2];//查询结果int cnt;int h[MAXN];int tt;int Q;//查询个数void add_query(int a,int b,int i)//边a 到 b,,第 i 次查询{query[tt].q=b;query[tt].next=h[a];query[tt].index=i;h[a]=tt++;query[tt].q=a;query[tt].next=h[b];query[tt].index=i;h[b]=tt++;}void init(int n)//传入n为结点总数{for(int i=1;i<=n;i++){F[i]=-1;r[i]=1;vis[i]=false;ancestor[i]=0;tol=0;tt=0;cnt=0;//已经查询到的个数}memset(head,-1,sizeof(head));memset(h,-1,sizeof(h));}int find(int x){if(F[x]==-1)return x;return F[x]=find(F[x]);}void Union(int x,int y)//合并{int t1=find(x);int t2=find(y);if(t1!=t2){if(r[t1]<=r[t2]){F[t1]=t2;r[t2]+=r[t1];}else{F[t2]=t1;r[t1]+=r[t2];}}}void LCA(int u){//if(cnt>=Q)return;//不要加这个ancestor[u]=u;vis[u]=true;//这个一定要放在前面for(int i=head[u];i!=-1;i=edge[i].next){int v=edge[i].to;if(vis[v])continue;LCA(v);Union(u,v);ancestor[find(u)]=u;}for(int i=h[u];i!=-1;i=query[i].next){int v=query[i].q;if(vis[v]){ans[query[i].index]=ancestor[find(v)];cnt++;//已经找到的答案数}}}bool flag[MAXN];int main(){int T;scanf("%d", &T);while(T–){int N;memset(flag, true, sizeof(flag));scanf("%d", &N);init(N);int u, v;for(int i=1;i<N;i++){scanf("%d%d", &u, &v);flag[v] = false;addedge(u, v);}Q = 1;scanf("%d%d", &u, &v);add_query(u, v, 1);int root;for(int i=1;i<=N;i++) if(flag[i])root = i;LCA(root);for(int i=1;i<=Q;i++)printf("%d\n", ans[i]);}return 0;}

经受雨,面对另一个轮回。

POJ 1330 Nearest Common ancesters(LCA,Tarjan离线算法)

相关文章:

你感兴趣的文章:

标签云: