POJ1330 Nearest Common Ancestors(倍增LCA算法求无边权树的模板)

模板题,注意要先判断根的编号。

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=1e5;
int N;
int head[maxn];
int tol;
struct node {
    int u;
    int v;
    int next;
}edge[maxn]; 
void addedge (int u,int v) {
    edge[tol].u=u;
    edge[tol].v=v;
    edge[tol].next=head[u];
    head[u]=tol++;
}

int h[maxn];
int father[20][maxn];
int isRoot[maxn];
void dfs (int x) {
    for (int i=head[x];i!=-1;i=edge[i].next) {
        int v=edge[i].v;
        if (v==father[0][x]) continue;
        father[0][v]=x;
        h[v]=h[x]+1;
        dfs(v);
    }
}
int lca (int x,int y) {
    if (h[x]<h[y]) swap(x,y);
    for (int i=17;i>=0;i--) 
        if (h[x]-h[y]>>i) x=father[i][x];
    if (x==y) return x;
    for (int i=17;i>=0;i--) {
        if (father[i][x]!=father[i][y]) {
            x=father[i][x];
            y=father[i][y];
        }
    }
    return father[0][x];
}

int main () {
    int T;
    scanf("%d",&T);
    while (T--) {
        scanf("%d",&N);
        memset(head,-1,sizeof(head));
        memset(isRoot,0,sizeof(isRoot));
        tol=0;
        memset(h,0,sizeof(h));
        memset(father,0,sizeof(father));
        for (int i=0;i<N-1;i++) {
            int u,v;
            scanf("%d%d",&u,&v);
            addedge(u,v);
            addedge(v,u);
            isRoot[v]=1;
        }
        int root;
        for (root=1;root<=N;root++)
            if (!isRoot[root]) break;
        dfs(root);
        for (int i=1;i<=17;i++)
            for (int j=1;j<=N;j++) 
                father[i][j]=father[i-1][father[i-1][j]];
        int x,y;
        scanf("%d%d",&x,&y);
        printf("%d
",lca(x,y));
    }
    return 0;
}
原文地址:https://www.cnblogs.com/zhanglichen/p/12527845.html