LCA 算法(二)倍增

 介绍一种解决最近公共祖先的在线算法,倍增,它是建立在任意整数的二进制拆分之上。

 

代码:

 

 1 //LCA:Doubly
 2 
 3 #include<cstdio>
 4 #define swap(a,b) a^=b^=a^=b
 5 #define maxn 500010
 6 using namespace std;
 7 
 8 int n,m,s,tot,head[maxn],deep[maxn],p[maxn][20];
 9 struct node
10 {
11     int nxt,to;
12 }edge[maxn<<1];
13 
14 int read()
15 {
16     int x=0,f=1;
17     char c=getchar();
18     while (c<48||c>57)
19         f=c=='-'?-1:1,c=getchar();
20     while (c>=48&&c<=57)
21         x=(x<<1)+(x<<3)+(c^48),c=getchar();
22     return x*f;
23 }
24 
25 void write(int x)
26 {
27     if (x<0)
28         x=-x,putchar('-');
29     if (x>=10)
30         write(x/10);
31     putchar(x%10+48);
32 }
33 
34 void add(int a,int b)
35 {
36     edge[++tot]=(node){head[a],b};
37     head[a]=tot;
38     edge[++tot]=(node){head[b],a};
39     head[b]=tot;
40 }
41 
42 void init()
43 {
44     for (int j=1;(1<<j)<=n;j++)
45         for (int i=1;i<=n;i++)
46             if (p[i][j-1])
47                 p[i][j]=p[p[i][j-1]][j-1];
48 }
49 
50 int dfs(int u)
51 {
52     for (int i=head[u];i;i=edge[i].nxt)
53         if (!deep[edge[i].to])
54         {
55             deep[edge[i].to]=deep[u]+1;
56             p[edge[i].to][0]=u;
57             dfs(edge[i].to);
58         }
59 }
60 
61 int LCA(int a,int b)
62 {
63     if (deep[a]<deep[b])
64         swap(a,b);
65     int i,j;
66     for (i=0;(1<<i)<=deep[a];i++);
67     i--;
68     for (j=i;j>=0;j--)
69         if (deep[b]<=deep[a]-(1<<j))
70             a=p[a][j];
71     if (a==b)
72         return a;
73     for (j=i;j>=0;j--)
74         if (p[a][j]!=p[b][j]&&deep[p[a][j]]>=1)
75         {
76             a=p[a][j];
77             b=p[b][j];
78         }
79     return p[a][0];
80 }
81 
82 int main()
83 {
84     int i,j,k;
85     n=read(),m=read(),s=read();
86     for (i=1;i<=n-1;i++)
87         add(read(),read());
88     deep[s]=1;
89     dfs(s);
90     init();
91     while (m--)
92         write(LCA(read(),read())),putchar(10);
93     return 0;
94 }

猜你喜欢

转载自www.cnblogs.com/Ronald-MOK1426/p/8999214.html