洛谷 P3379 【模板】最近公共祖先(LCA)
题目描述
如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先。
输入输出格式
输入格式:
第一行包含三个正整数N、M、S,分别表示树的结点个数、询问的个数和树根结点的序号。
接下来N-1行每行包含两个正整数x、y,表示x结点和y结点之间有一条直接连接的边(数据保证可以构成树)。
接下来M行每行包含两个正整数a、b,表示询问a结点和b结点的最近公共祖先。
输出格式:
输出包含M行,每行包含一个正整数,依次为每一个询问的结果。
输入输出样例
说明
时空限制:1000ms,128M
数据规模:
对于30%的数据:N<=10,M<=10
对于70%的数据:N<=10000,M<=10000
对于100%的数据:N<=500000,M<=500000
样例说明:
该树结构如下:
第一次询问:2、4的最近公共祖先,故为4。
第二次询问:3、2的最近公共祖先,故为4。
第三次询问:3、5的最近公共祖先,故为1。
第四次询问:1、2的最近公共祖先,故为4。
第五次询问:4、5的最近公共祖先,故为4。
故输出依次为4、4、1、4、4。
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 using namespace std; 5 long long read() 6 { 7 long long x=0,f=1; 8 char ch=getchar(); 9 while(ch>'9'||ch<'0') 10 { 11 if(ch=='-') 12 f=-1; 13 ch=getchar(); 14 } 15 while(ch>='0'&&ch<='9') 16 { 17 x=x*10+ch-'0'; 18 ch=getchar(); 19 } 20 return x*f; 21 } 22 const int maxn=500005; 23 int n,m,s,k,a,b; 24 int head[maxn],d[maxn],p[maxn][21]; 25 struct node 26 { 27 int v,next; 28 } e[maxn*2]; 29 void add(int u,int v) 30 { 31 e[k].v=v; 32 e[k].next=head[u]; 33 head[u]=k++; 34 } 35 void dfs(int u,int fa) 36 { 37 d[u]=d[fa]+1; 38 p[u][0]=fa; 39 for(int i=1; (1<<i)<=d[u]; i++) 40 p[u][i]=p[p[u][i-1]][i-1]; 41 for(int i=head[u]; i!=-1; i=e[i].next) 42 { 43 int v=e[i].v; 44 if(v!=fa) 45 dfs(v,u); 46 } 47 } 48 int lca(int a,int b) 49 { 50 if(d[a]>d[b]) 51 swap(a,b); 52 for(int i=20; i>=0; i--) 53 if(d[a]<=d[b]-(1<<i)) 54 b=p[b][i]; 55 if(a==b) 56 return a; 57 for(int i=20; i>=0; i--) 58 { 59 if(p[a][i]==p[b][i]) 60 continue; 61 else 62 a=p[a][i],b=p[b][i]; 63 } 64 return p[a][0]; 65 } 66 int main() 67 { 68 memset(head,-1,sizeof(head)); 69 n=read(),m=read(),s=read(); 70 for(int i=1; i<n; i++) 71 { 72 a=read(),b=read(); 73 add(a,b); 74 add(b,a); 75 } 76 dfs(s,0); 77 for(int i=1; i<=m; i++) 78 { 79 a=read(),b=read(); 80 printf("%d\n",lca(a,b)); 81 } 82 return 0; 83 }
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 using namespace std; 5 const int maxn=2e6+10; 6 #define ls k<<1 7 #define rs k<<1|1 8 long long read() 9 { 10 long long x=0,f=1; 11 char ch=getchar(); 12 while(ch>'9'||ch<'0') 13 { 14 if(ch=='-') 15 f=-1; 16 ch=getchar(); 17 } 18 while(ch>='0'&&ch<='9') 19 { 20 x=x*10+ch-'0'; 21 ch=getchar(); 22 } 23 return x*f; 24 } 25 struct node 26 { 27 int v,nxt; 28 } e[maxn]; 29 int head[maxn],fa[maxn],deep[maxn],tot[maxn],son[maxn],top[maxn]; 30 int num=1,cnt; 31 void add(int x,int y) 32 { 33 e[num].v=y; 34 e[num].nxt=head[x]; 35 head[x]=num++; 36 } 37 int dfs1(int now,int f,int dep) 38 { 39 deep[now]=dep; 40 fa[now]=f; 41 tot[now]=1; 42 int maxson=-1; 43 for(int i=head[now]; i; i=e[i].nxt) 44 { 45 if(e[i].v==f) 46 continue; 47 tot[now]+=dfs1(e[i].v,now,dep+1); 48 if(tot[e[i].v]>maxson) 49 maxson=tot[e[i].v],son[now]=e[i].v; 50 } 51 return tot[now]; 52 } 53 void dfs2(int now,int topf) 54 { 55 top[now]=topf; 56 if(!son[now]) 57 return ; 58 dfs2(son[now],topf); 59 for(int i=head[now]; i; i=e[i].nxt) 60 if(e[i].v!=son[now]&&e[i].v!=fa[now]) 61 dfs2(e[i].v,e[i].v); 62 } 63 int LCA(int x,int y) 64 { 65 while(top[x]!=top[y]) 66 { 67 if(deep[top[x]]<deep[top[y]]) 68 swap(x,y); 69 x=fa[top[x]]; 70 } 71 if(deep[x]>deep[y]) 72 swap(x,y); 73 return x; 74 } 75 int main() 76 { 77 memset(head,0,sizeof(head)); 78 int n=read(),m=read(),root=read(); 79 for(int i=1; i<=n-1; i++) 80 { 81 int x=read(),y=read(); 82 add(x,y),add(y,x); 83 } 84 dfs1(root,0,1); 85 dfs2(root,root); 86 while(m--) 87 { 88 int x=read(),y=read(); 89 printf("%d\n",LCA(x,y)); 90 } 91 return 0; 92 }