【LCA】最近の公的祖先を求める

2064 ワード

アルゴリズム1:オンラインアルゴリズム倍増
POJ 1330テンプレート問題
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h>
using namespace std;
#define maxn 10010

int point[maxn*2],next[maxn*2],last[maxn],tot,dep[maxn];
int fa[maxn][20],T,n,root,a,b;
bool flag[maxn];

     
void add(int x,int y){
     point[++tot]=y;
     next[tot]=last[x];
     last[x]=tot;
     }

void clear(){
      memset(flag,true,sizeof(flag));
      tot=0;
      memset(last,0,sizeof(last));
      }
      
void bfs(int root)
{
     queue<int>q;
     dep[root]=1;
     q.push(root);
     int i,j;
     while (!q.empty())
     {
         int tmp=q.front();
         q.pop();
         for (i=last[tmp];i;i=next[i])
         {
            int v=point[i];
            if (v==fa[tmp][0]) continue;
            dep[v]=dep[tmp]+1;
            fa[v][0]=tmp;
            q.push(v);
         }
         for (i=fa[tmp][0],j=0;i;i=fa[j][j++])
          fa[tmp][j+1]=fa[j][j];
     }
     
}        

int LCA(int u,int v)
{
     if (dep[u]<dep[v]) swap(u,v);
     int i;
     while (dep[u]>dep[v]){
        for (i=0;dep[fa[u][i]]>=dep[v];i++);
        u=fa[u][i-1];
        }
     while (u!=v){
           for (i=1;fa[u][i]!=fa[v][i];i++);
           u=fa[u][i-1];
           v=fa[v][i-1];
           }
     return u;
}
      
int main()
{ 
   scanf("%d",&T);
   while (T--){
      clear();
      scanf("%d",&n);
      for (int i=1;i<n;i++){
          scanf("%d%d",&a,&b);
          add(a,b);
          add(b,a);
          flag[b]=false;
          }
      for (int i=1;i<=n;i++)
         if (flag[i]){
            root=i;
            break;
            }
      bfs(root);
      int u,v;
      scanf("%d%d",&u,&v);
      printf("%d
",LCA(u,v)); } }