倍增法

  1 /*
  2   Source   :
  3   Problem  : 求最近公共祖先的倍增算法
  4   Solution :
  5   Date     :2018-08-16-16.45
  6 */
  7 
  8 // #include <bits/stdc++.h>
  9 #include<cstdio>
 10 #include <cstdlib>
 11 #include <cstring>
 12 #include <iostream>
 13 using namespace std;
 14 
 15 typedef long long LL;
 16 const int MAXN = 100005;
 17 const LL MOD7 = 1e9+7;
 18 
 19 struct Edge
 20 {
 21     int u,v;
 22     int next;
 23 }edge[2*MAXN];
 24 int head[MAXN];
 25 int cnt;
 26 int n;
 27 
 28 void addEdge(int u,int v)
 29 {
 30     edge[cnt].u=u;edge[cnt].v=v;edge[cnt].next=head[u];head[u]=cnt++;
 31 }
 32 void init()
 33 {
 34     memset(head,-1,sizeof(head));
 35     cnt=0;
 36 }
 37 
 38 int dep[MAXN];
 39 int f[MAXN][20];
 40 
 41 void dfs(int u,int pre)
 42 {
 43     f[u][0]=pre;
 44     for (int i=head[u];i!=-1;i=edge[i].next)
 45     {
 46         int v=edge[i].v;
 47         // if (v==pre) continue;
 48         dep[v]=dep[u]+1;
 49         dfs(v,u);
 50     }
 51 }
 52 
 53 void BZ()
 54 {
 55     for (int j=1;j<20;++j)
 56     {
 57         for (int i=1;i<=n;++i)
 58         {
 59             if (f[i][j-1])
 60             {
 61                 f[i][j]=f[f[i][j-1]][j-1];
 62             }
 63         }
 64     }
 65 }
 66 
 67 int LCA(int u,int v)
 68 {
 69     if (dep[u]<dep[v]) swap(u,v);
 70     int delta = dep[u]-dep[v];
 71     for (int i=0;i<20;++i)
 72     {
 73         if (delta&(1<<i)) u = f[u][i];
 74     }
 75     if (u==v) return u;
 76     for (int i=19;i>=0;--i)
 77     {
 78         if (f[u][i]!=f[v][i])
 79         {
 80             u=f[u][i];
 81             v=f[v][i];
 82         }
 83     }
 84     return f[u][0];
 85 }
 86 
 87 int in[MAXN];
 88 
 89 int main()
 90 {
 91 #ifndef ONLINE_JUDGE
 92     freopen("test.txt","r",stdin);
 93 #endif // ONLINE_JUDGE
 94     int Case;
 95     scanf("%d",&Case);
 96     while (Case--)
 97     {
 98         scanf("%d",&n);
 99         init();
100         int u,v;
101         int root=-1;
102         memset(in,0,sizeof(in));
103         for (int i=1;i<n;++i)
104         {
105             scanf("%d%d",&u,&v);
106             addEdge(u,v);
107             in[v]++;
108             // f[v][0]=u;
109         }
110         for (int i=1;i<=n;++i)
111             if (in[i]==0)
112         {
113             root=i;
114             break;
115         }
116         dep[root]=1;
117         dfs(root,0);
118         BZ();
119         int Q;
120         Q=1;
121         for (int i=1;i<=Q;++i)
122         {
123             scanf("%d%d",&u,&v);
124             printf("%d\n",LCA(u,v));
125         }
126     }
127     return 0;
128 }

 

posted @ 2018-08-16 17:35  LeeSongt  阅读(336)  评论(0编辑  收藏  举报