华师一附中OI组

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 916|回复: 1
打印 上一主题 下一主题

P3379 【模板】最近公共祖先(LCA)

[复制链接]

738

主题

1485

帖子

5420

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
5420
跳转到指定楼层
楼主
发表于 2018-5-21 22:32:21 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
https://www.luogu.org/problemnew/show/P3379

题目描述
如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先。

输入输出格式
输入格式:
第一行包含三个正整数N、M、S,分别表示树的结点个数、询问的个数和树根结点的序号。

接下来N-1行每行包含两个正整数x、y,表示x结点和y结点之间有一条直接连接的边(数据保证可以构成树)。

接下来M行每行包含两个正整数a、b,表示询问a结点和b结点的最近公共祖先。

输出格式:
输出包含M行,每行包含一个正整数,依次为每一个询问的结果。

输入输出样例
输入样例#1:
5 5 4
3 1
2 4
5 1
1 4
2 4
3 2
3 5
1 2
4 5
输出样例#1:
4
4
1
4
4
说明
时空限制: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。
回复

使用道具 举报

14

主题

106

帖子

317

积分

中级会员

Rank: 3Rank: 3

积分
317
沙发
发表于 2018-10-21 20:47:26 | 只看该作者
  1. #include<iostream>
  2. #include<cstdio>
  3. using namespace std;
  4. #define FOR(i,a,b) for(int i=a;i<=b;i++)
  5. #define For(i,a,b) for(int i=a;i>=b;i--)
  6. const int MX=500010;
  7. int first[MX],next[MX*2],dep[MX],f[MX][25];
  8. int uu[MX*2],vv[MX*2],fath[MX],n,root,t,tt,m,la;
  9. int getint()
  10. {
  11.     int w = 0, q = 0;
  12.     char c = getchar();
  13.     while ((c < '0' || c > '9') && c != '-') c = getchar();
  14.     if (c == '-')  q = 1, c = getchar();
  15.     while (c >= '0' && c <= '9') w = w * 10 + c - '0', c = getchar();
  16.     return q ? -w : w;
  17. }
  18. void scan()
  19. {
  20.     scanf("%d %d %d",&n,&m,&root);
  21.     FOR(i,1,n-1)
  22.     {
  23.         uu[i]=getint();
  24.         vv[i]=getint();
  25.         uu[i+n]=vv[i];
  26.         vv[i+n]=uu[i];
  27.     }
  28.     FOR(i,1,2*n)
  29.     {
  30.         next[i]=first[uu[i]];
  31.         first[uu[i]]=i;
  32.     }
  33. }
  34. void pre(int u,int fa)
  35. {
  36.     dep[u]=dep[fa]+1;
  37.     FOR(i,1,20) f[u][i]=f[f[u][i-1]][i-1];
  38.     for(int i=first[u];i!=0;i=next[i])
  39.     {
  40.         if(vv[i]==fa) continue;
  41.         f[vv[i]][0]=uu[i];
  42.         pre(vv[i],uu[i]);
  43.     }
  44. }
  45. int lca(int x,int y)
  46. {
  47.     if(x==y) return x;
  48.     if(dep[x]<dep[y]) swap(x,y);
  49.     For(i,20,0)
  50.     {
  51.         if(dep[f[x][i]]>=dep[y]) x=f[x][i];
  52.         if(dep[x]==dep[y]) break;
  53.     }
  54.     if(x==y) return x;
  55.     For(i,20,0)
  56.         if(f[x][i]!=f[y][i])
  57.         {
  58.             x=f[x][i];
  59.             y=f[y][i];
  60.         }
  61.     return f[x][0];
  62. }
  63. int main()
  64. {
  65.     scan();pre(root,0);
  66.     FOR(kk,1,m)
  67.     {
  68.         t=getint();
  69.         tt=getint();
  70.         printf("%d\n",lca(t,tt));
  71.     }
  72.     return 0;
  73. }
复制代码
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|服务支持:DZ动力|华师一附中OI组  

GMT+8, 2024-11-2 04:40 , Processed in 0.239716 second(s), 23 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表