给一棵树,查询两个点的最近公共祖先。还是模板题,不过数据给的时候是按顺序给的,所以要直接存成从根节点到叶子节点的有向图,同时存一下每个点的入度用来找根节点,然后从根节点开始做一遍tarjan就行..

   

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <memory.h>
#include <cmath>
using namespace std;
typedef long long ll;
const int maxn=40000+40;
struct node
{
    int w,v;
    int next;
}edge[maxn<<1],query[500];
bool vis[maxn];
int g[maxn],gg[maxn];
int res[maxn][3];
int m,n,k,p,q;
int en,eq;
int test;
int fa[maxn];
int dis[maxn];
int find(int x)
{
    if (x!=fa[x]) return fa[x]=find(fa[x]);
    return x;
}
void tarjan(int u)
{
    vis[u]=true;
    fa[u]=u;
    for (int j=gg[u]; j!=-1; j=query[j].next)
    {
        if (vis[query[j].v])
        {
            res[query[j].w][2]=find(query[j].v);
        }
    }
    for (int j=g[u]; j!=-1; j=edge[j].next)
    {
        if (!vis[edge[j].v])
        {
            dis[edge[j].v]=dis[u]+edge[j].w;
            tarjan(edge[j].v);
            fa[edge[j].v]=u;
        }
    }
}
int ideg[maxn];
int main()
{
//    freopen("in.txt","r",stdin);
    scanf("%d",&test);
    while (test--)
    {
        memset(vis,false,sizeof vis);
        memset(dis,0,sizeof dis);
        memset(ideg,0,sizeof ideg);
        scanf("%d",&n);
//        scanf("%d",&m);
        m=1;
        memset(g,-1,sizeof g);
        memset(gg,-1,sizeof gg);

        en=eq=0;
        int x,y,z;
        int root=-1;
        for (int i=1; i<n; i++)
        {
            scanf("%d%d",&x,&y);
            ideg[y]++;
            if (root==-1) root=x;
            z=1;
            edge[en].w=z;
            edge[en].v=y;
            edge[en].next=g[x];
            g[x]=en;
            en++;
        }


        for (int i=1; i<=m; i++)
        {
            scanf("%d%d",&x,&y);
            query[eq].v=y;
            query[eq].w=i;
            query[eq].next=gg[x];
            gg[x]=eq;
            eq++;

            query[eq].v=x;
            query[eq].w=i;
            query[eq].next=gg[y];
            gg[y]=eq;
            eq++;

            res[i][0]=x;
            res[i][1]=y;
        }

        for (int i=1; i<=n; i++)
        if (ideg[i]==0)
        {
            root=i;
            break;
        }
        dis[root]=0;
        tarjan(root);
        cout<<res[1][2]<<endl;


    }
    return 0;
}