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

题目描述

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

输入输出格式

输入格式:

第一行包含三个正整数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. #include <bits/stdc++.h>
  2. inline void read(int &x){x = 0;char ch = getchar();char c = ch;while(ch > '9' || ch < '0')c = ch, ch = getchar();while(ch <= '9' && ch >= '0')x = x * 10 + ch - '0', ch = getchar();if(c == '-')x = -x;}
  3. inline void read(long long &x){x = 0;char ch = getchar();char c = ch;while(ch > '9' || ch < '0')c = ch, ch = getchar();while(ch <= '9' && ch >= '0')x = x * 10 + ch - '0', ch = getchar();if(c == '-')x = -x;}
  4. const int INF = 0x3f3f3f3f;
  5. const int MAXN = 500000 + 10;
  6. const int MAXM = 500000 + 10;
  7.  
  8. long long n,m,root;
  9.  
  10. struct Edge
  11. {
  12. int u,v,next;
  13. }edge[(MAXN << 1) + 10];
  14. int head[MAXN],cnt;
  15. inline void insert(int a,int b){edge[++cnt] = Edge{a,b,head[a]};head[a] = cnt;}
  16.  
  17. struct qEdge
  18. {
  19. int u,v,next,ans;
  20. }qedge[(MAXM << 1) + 20];
  21. int qhead[MAXM], qcnt;
  22. inline void qinsert(int a,int b){qedge[++qcnt] = qEdge{a,b,qhead[a],0};qhead[a] = qcnt;}
  23.  
  24. int tmp1,tmp2;
  25.  
  26. bool b[MAXN];
  27. int fa[MAXN];
  28.  
  29. //并查集
  30.  
  31. int find(int x)
  32. {
  33. return x == fa[x] ? fa[x] : fa[x] = find(fa[x]);
  34. }
  35.  
  36. void merge(int a, int b)
  37. {
  38. int tmp1 = find(a);int tmp2 = find(b);
  39. if(tmp1 == tmp2)
  40. {
  41. return;
  42. }
  43. else
  44. {
  45. fa[tmp2] = find(tmp1);
  46. }
  47. }
  48.  
  49. void dfs(int u)
  50. {
  51. for(int pos = head[u];pos;pos = edge[pos].next)
  52. {
  53. int v = edge[pos].v;
  54. if(!b[v])
  55. {
  56. b[v] = true;
  57. dfs(v);
  58. merge(u, v);//把v指向u合并
  59. }
  60. }
  61. for(int pos = qhead[u];pos;pos = qedge[pos].next)
  62. {
  63. int v = qedge[pos].v;
  64. if(b[v])
  65. {
  66. int tmp = find(v);
  67. qedge[pos].ans = tmp;
  68. if(pos & 1)
  69. {
  70. qedge[pos + 1].ans = tmp;
  71. }
  72. else
  73. {
  74. qedge[pos - 1].ans = tmp;
  75. }
  76. }
  77. }
  78. }
  79.  
  80. void tarjan()
  81. {
  82. for(int i = 1;i <= n;i ++)
  83. {
  84. fa[i] = i;
  85. }
  86. b[root] = true;
  87. dfs(root);
  88. }
  89. int main()
  90. {
  91. read(n);read(m);read(root);
  92. for(int i = 1;i < n;i ++)
  93. {
  94. read(tmp1);read(tmp2);
  95. insert(tmp1, tmp2);
  96. insert(tmp2, tmp1);
  97. }
  98. for(int i = 1;i <= m;i ++)
  99. {
  100. read(tmp1);read(tmp2);
  101. qinsert(tmp1, tmp2);
  102. qinsert(tmp2, tmp1);
  103. }
  104. tarjan();
  105. for(int i = 1;i <= m;i ++)
  106. {
  107. printf("%d\n", qedge[i * 2].ans);
  108. }
  109. return 0;
  110. }

【模板】tarjanLCA [2017年6月计划 学习tarjanLCA]的更多相关文章

  1. 【模板】Tarjan缩点,强连通分量 洛谷P2341 [HAOI2006]受欢迎的牛 [2017年6月计划 强连通分量01]

    P2341 [HAOI2006]受欢迎的牛 题目描述 每头奶牛都梦想成为牛棚里的明星.被所有奶牛喜欢的奶牛就是一头明星奶牛.所有奶 牛都是自恋狂,每头奶牛总是喜欢自己的.奶牛之间的“喜欢”是可以传递的 ...

  2. 【模板】倍增LCA [2017年5月计划 清北学堂51精英班 Day3]

    P3379 [模板]最近公共祖先(LCA) 题目描述 如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 输入输出格式 输入格式: 第一行包含三个正整数N.M.S,分别表示树的结点个数.询 ...

  3. 【模板】KMP [2017年5月计划 清北学堂51精英班Day2]

    Day2就搞一个KMP把  马拉车.AC自动机等准备省选的时候再说.. 模板题: 1204 寻找子串位置 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 青铜 Bronze     ...

  4. 【模板】LIS模板 洛谷P1091 [NOIP2004提高组]合唱队形 [2017年4月计划 动态规划11]

    以题写模板. 写了两个:n^2版本与nlogn版本 P1091 合唱队形 题目描述 N位同学站成一排,音乐老师要请其中的(N-K)位同学出列,使得剩下的K位同学排成合唱队形. 合唱队形是指这样的一种队 ...

  5. 【模板】tyvjP1520 树的直径 [2017年5月计划 清北学堂51精英班Day3]

    P1520 树的直径 时间: 1000ms / 空间: 131072KiB / Java类名: Main 描述 树的直径,即这棵树中距离最远的两个结点的距离.每两个相邻的结点的距离为1,即父亲结点与儿 ...

  6. 2017年7月ROS学习资料小结

    <孙子兵法·谋攻篇>:"上兵伐谋,其次伐交,其次伐兵,其下攻城:攻城之法为不得已." 任何发生在自己国土上的战争,即便胜利,也饱含屈辱. ----~~~~----Gaz ...

  7. RQNOJ PID192 梦幻大PK [2017年6月计划 二分图02]

    PID192 / 梦幻大PK ☆ 提交你的代码 查看讨论和题解 你还木有做过哦 我的状态         查看最后一次评测记录 质量 7 题目评价 质量 7 ★★★★★ ★★★★☆ ★★★☆☆ ★★☆ ...

  8. 【CodeVS】2822 爱在心中 [2017年6月计划 强连通分量03]

    2822 爱在心中 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond         题目描述 Description “每个人都拥有一个梦,即使彼此不相同,能够 ...

  9. 洛谷P2912 [USACO08OCT]牧场散步Pasture Walking [2017年7月计划 树上问题 01]

    P2912 [USACO08OCT]牧场散步Pasture Walking 题目描述 The N cows (2 <= N <= 1,000) conveniently numbered ...

随机推荐

  1. vue爬坑之input组件

    本篇写给第一次用VUE写输入框组件的朋友们 正常情况我们vue2.0是怎么样取到input框的值的呢? 很简单只需要给input框设置v-model="val" 我们就能从data ...

  2. 一个事件一定时间内只允许点击执行一次 与 vue阻止滚动穿透

    可能我的方法很笨,简单实现来的就是给两个状态,一个状态点击时就发生改变,另外一个给一个定时器延迟改变 篮圈部分,给了两种状态,一个isDisable,一个comeTime 点击事件以后comeTime ...

  3. LeeCode-Single Number III

    Given an array of numbers nums, in which exactly two elements appear only once and all the other ele ...

  4. springboot 2+ druid

    springboot 1+ druid druid 配置 import com.alibaba.druid.pool.DruidDataSource; import com.alibaba.druid ...

  5. hammer.js使用

    手势包括点击(tap),长按(press),滑动(swipe),方向(pan) 使用实例: <!DOCTYPE html> <html> <head> <me ...

  6. [欧拉路]CF1152E Neko and Flashback

    1152E - Neko and Flashback 题意:对于长为n的序列c和长为n - 1的排列p,我们可以按照如下方法得到长为n - 1的序列a,b,a',b'. ai = min(ci, ci ...

  7. day48作业

    使用Bootstrap框架编写一个简单的web静态页面 效果图: <!DOCTYPE html> <html lang="en"> <head> ...

  8. jeecms获取绝对路径

    jeecms后台管理做一个附件上传到服务器上,然后读取改上传文件,半天获取不到路径,后来发现有定义好的绝对路径获取方法: //最好将文件上传到u文件夹底下 String path="/u/c ...

  9. 【agc013d】AtCoder Grand Contest 013 D - Piling Up

    题意 盒子里有n块砖,每块的颜色可能为蓝色或红色. 执行m次三步操作: 1.从盒子里随便拿走一块砖 2.放入一块蓝砖和红砖到盒子里 3.从盒子里随便拿走一块砖 给定n,m 问拿出来的砖,可能有多少种不 ...

  10. DAO设计模式总结

    1.DAO(Data Access Object,数据访问对象),主要的功能是用于进行数据操作的,在程序的标准开发框架中属于数据层的操作. 数据开发结构流程: 资源层是数据库的操作层,里面可以进行各种 ...