题目描述

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

输入输出格式

输入格式:

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

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

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

输出格式:

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

输入输出样例

输入样例#1:

  1. 5 5 4
  2. 3 1
  3. 2 4
  4. 5 1
  5. 1 4
  6. 2 4
  7. 3 2
  8. 3 5
  9. 1 2
  10. 4 5
输出样例#1:

  1. 4
  2. 4
  3. 1
  4. 4
  5. 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。

  1. //就是个板子,但是各种卡还要用读入优化...
  2. //边不要用vector存会超时!!!
  3. #include<iostream>
  4. #include<cstdio>
  5. #include<cstring>
  6. #define maxn 500010
  7. #define S 21
  8.  
  9. using namespace std;
  10. int deep[maxn],head[maxn],p1,p2,n,m,num,ans,s,x,y,fa[maxn][S+];
  11. struct node {
  12. int from;
  13. int to;
  14. int next;
  15. }e[maxn*];
  16.  
  17. void add(int from,int to)
  18. {
  19. e[++num].from=from;
  20. e[num].to=to;
  21. e[num].next=head[from];
  22. head[from]=num;
  23. }
  24.  
  25. int init()
  26. {
  27. int x=,f=;char c=getchar();
  28. while(c>''||c<''){if(c=='-')f=-;c=getchar();}
  29. while(c>=''&&c<=''){x=x*+c-'';c=getchar();}
  30. return x*f;
  31. }
  32.  
  33. void swap(int &a,int &b)
  34. {
  35. int t=a;a=b;b=t;
  36. }
  37.  
  38. void get_fa()
  39. {
  40. for(int j=;j<=S;j++)
  41. for(int i=;i<=n;i++)
  42. fa[i][j]=fa[fa[i][j-]][j-];
  43. }
  44.  
  45. void Dfs(int now,int from,int c)
  46. {
  47. fa[now][]=from;
  48. deep[now]=c;
  49. for(int i=head[now];i;i=e[i].next)
  50. {
  51. int v=e[i].to;
  52. if(v!=from)
  53. Dfs(v,now,c+);
  54. }
  55. }
  56.  
  57. int get_same(int a,int t)
  58. {
  59. for(int i=;i<S;i++)
  60. if(t&(<<i)) a=fa[a][i];
  61. return a;
  62. }
  63.  
  64. int LCA(int a,int b)
  65. {
  66. if(deep[a]<deep[b]) swap(a,b);
  67. a=get_same(a,deep[a]-deep[b]);
  68. if(a==b) return a;
  69. for(int i=S;i>=;i--)
  70.  
  71. {
  72. if(fa[a][i]!=fa[b][i])
  73. {
  74. a=fa[a][i];
  75. b=fa[b][i];
  76. }
  77. }
  78. return fa[a][];
  79. }
  80.  
  81. int main()
  82. {
  83. n=init();m=init();s=init();
  84. int x,y;
  85. for(int i=;i<n;i++)
  86. {
  87. x=init();y=init();
  88. add(x,y);
  89. add(y,x);
  90. }
  91. Dfs(s,s,);
  92. get_fa();
  93. for(int i=;i<=m;i++)
  94. {
  95. p1=init();p2=init();
  96. int ans=LCA(p1,p2);
  97. printf("%d\n",ans);
  98. }
  99. return ;
  100. }

P3379最近公共祖先(LCA)的更多相关文章

  1. Luogu 2245 星际导航(最小生成树,最近公共祖先LCA,并查集)

    Luogu 2245 星际导航(最小生成树,最近公共祖先LCA,并查集) Description sideman做好了回到Gliese 星球的硬件准备,但是sideman的导航系统还没有完全设计好.为 ...

  2. POJ 1470 Closest Common Ancestors(最近公共祖先 LCA)

    POJ 1470 Closest Common Ancestors(最近公共祖先 LCA) Description Write a program that takes as input a root ...

  3. POJ 1330 Nearest Common Ancestors / UVALive 2525 Nearest Common Ancestors (最近公共祖先LCA)

    POJ 1330 Nearest Common Ancestors / UVALive 2525 Nearest Common Ancestors (最近公共祖先LCA) Description A ...

  4. [模板] 最近公共祖先/lca

    简介 最近公共祖先 \(lca(a,b)\) 指的是a到根的路径和b到n的路径的深度最大的公共点. 定理. 以 \(r\) 为根的树上的路径 \((a,b) = (r,a) + (r,b) - 2 * ...

  5. 【lhyaaa】最近公共祖先LCA——倍增!!!

    高级的算法——倍增!!! 根据LCA的定义,我们可以知道假如有两个节点x和y,则LCA(x,y)是 x 到根的路 径与 y 到根的路径的交汇点,同时也是 x 和 y 之间所有路径中深度最小的节 点,所 ...

  6. P3379 最近公共祖先(LCA) 洛谷

    题意简单明了(这就是个模板). 就是让我们找2个节点的公共祖先而已,但我们要讲的做法不是生硬的爆搜,而且直接搜好像过不去…… 这次就讲我往后拖了n多天才开始学了倍增LCA. 嗯,这个题,如果2个节点的 ...

  7. 最近公共祖先 lca (施工ing)

    声明 咳咳,进入重难点的图论算法之一(敲黑板): 题目: 洛谷 P3379 先放标程,施工ing,以后补坑!!!(实在太难,一个模板这么长 [ 不过好像还是没有 AC自动机 长哎 ],注释都打半天,思 ...

  8. 图论2 最近公共祖先LCA

    模板 吸取洛谷P3379的教训,我决定换板子(其实本质都是倍增是一样的),把vector换成了边表 输入格式: 第一行包含三个正整数N.M.S,分别表示树的结点个数.询问的个数和树根结点的序号. 接下 ...

  9. 学习笔记--最近公共祖先(LCA)的几种求法

    前言: 给定一个有根树,若节点\(z\)是两节点\(x,y\)所有公共祖先深度最大的那一个,则称\(z\)是\(x,y\)的最近公共祖先(\(Least Common Ancestors\)),简称\ ...

随机推荐

  1. 使用JavaScript制作一个好看的轮播图

    目录 使用JavaScript制作出好看的轮播图效果 准备材料 1.图片若干张(包括轮播图和按钮的图片) 2.将按钮的图片应用到按钮上的CSS样式文件 3.实现轮播和点击跳转的JavaScript代码 ...

  2. [angular2]解决安装 angular-cli 报错:Cannot find module 'github-url-from-git'

    1.运行:sudo rm -rf /usr/local/lib/node_modules/npm 2.重新安装最新版本的node,最新版本的node已经集成了npm,所以无需另外安装. 3.运行:su ...

  3. linux常用操作记录

    vim:多行注释 vim中多行注释和多行删除命令,这些命令也是经常用到的一些小技巧,可以大大提高工作效率.   多行注释:   1. 首先按esc进入命令行模式下,按下Ctrl + v,进入列(也叫区 ...

  4. intel compiler的表现

    好久没弄这个东西,今天突然想试下,代码没写完,以后补. #include <stdio.h> #include <stdlib.h> #include <time.h&g ...

  5. codeforces 372 Complete the Word(双指针)

    codeforces 372 Complete the Word(双指针) 题链 题意:给出一个字符串,其中'?'代表这个字符是可变的,要求一个连续的26位长的串,其中每个字母都只出现一次 #incl ...

  6. PAT 1131 Subway Map

    In the big cities, the subway systems always look so complex to the visitors. To give you some sense ...

  7. 【Codeforces 411A】Password Check

    [链接] 我是链接,点我呀:) [题意] 题意 [题解] 傻逼模拟题 [代码] import java.io.*; import java.util.*; public class Main { st ...

  8. UVA 12686 Trending Topic

    Trending Topic Time limit: 1.000 seconds Imagine you are in the hiring process for a company whose p ...

  9. BNUOJ 33898 Cannon

    Cannon Time Limit: 1000ms Memory Limit: 65535KB This problem will be judged on HDU. Original ID: 449 ...

  10. 【BZOJ4650&UOJ219】优秀的拆分(二分,hash)

    题意: 思路: 在实现时SA可以用hash+二分代替,会多一个log BZ上跑的飞快,但UOJ上extra卡出翔,已经放弃 不过转C或者写SA没准就过了 看来转C迫在眉睫 ; ..]of int64; ...