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

来源:互联网 发布:ubuntu dash 删除 编辑:程序博客网 时间:2024/04/27 13:29

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;}



0 0
原创粉丝点击