首先这个题 很毒瘤 被数据卡了 很长时间
题目描述
如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先。
输入输出格式
输入格式:
第一行包含三个正整数N、M、S,分别表示树的结点个数、询问的个数和树根结点的序号。
接下来N-1行每行包含两个正整数x、y,表示x结点和y结点之间有一条直接连接的边(数据保证可以构成树)。
接下来M行每行包含两个正整数a、b,表示询问a结点和b结点的最近公共祖先。
输出格式:
输出包含M行,每行包含一个正整数,依次为每一个询问的结果。
解析
结构体 来存 邻接表
d数组表示 这个点 的 深度
f 数组 表示 i 向上跳 2^k 步的点
CODE:
1 #include<cstdio> 2 #include<iostream> 3 using namespace std; 4 int n,m,s,num; 5 int d[500001],f[21][500001]; 6 int lin[1000001]; 7 struct qwq{ 8 int to,next; 9 }zh[10000001]; 10 void add(int x,int y)//邻接表 存 图 11 { 12 num++; 13 zh[num].to=y;// x 能到达的点 14 zh[num].next=lin[x]; 15 lin[x]=num; 16 } 17 void dfs(int x,int y) 18 { 19 d[x]=d[y]+1; 20 f[0][x]=y; 21 for(int k=1;d[x]>=(1<<k);k++)// 限制条件是 不能跳出这个 树 22 f[k][x]=f[k-1][f[k-1][x]];//f表示i向上跳2^k步的点 23 for(int i=lin[x];i;i=zh[i].next) 24 if(zh[i].to!=y) 25 dfs(zh[i].to,x); 26 } 27 int LCA(int u,int v) 28 { 29 if(d[u]<d[v])//d表示这个点的深度 30 swap(u,v); 31 for(int k=20;k>=0;k--) 32 { 33 if(d[f[k][u]]>=d[v])// 不能跳的超过v 34 u=f[k][u]; 35 } 36 if(u==v) 37 return u; 38 for(int k=20;k>=0;k--) 39 { 40 if(f[k][u]!=f[k][v])// 公共点不能和跳到同样高的点,不然无法区分 这是不是最近的 41 u=f[k][u],v=f[k][v]; 42 } 43 return f[0][u]; 44 } 45 int main() 46 { 47 scanf("%d%d%d",&n,&m,&s); 48 for(int i=1;i<n;i++) 49 { 50 int x,y; 51 scanf("%d%d",&x,&y); 52 add(x,y),add(y,x); // 双向边 53 } 54 dfs(s,0); 55 for(int i=1;i<=m;i++) 56 { 57 int x,y; 58 scanf("%d%d",&x,&y); 59 printf("%d ",LCA(x,y)); 60 } 61 return 0; 62 }