先记录以1为根时每个节点子树儿子节点的最大与次小值,询问x, y时,先判断x在不在y的子树范围内,若不在,结果为y的儿子结点,后继的最小值。

若x在y的子树范围内,若y儿子最小值是x的前驱,从次小值与父亲节点转移,否则从最小值与父亲节点转移。

  1. #include<cstdio>
  2. #include<iostream>
  3. #include<cstdlib>
  4. #include<cstring>
  5. #include<string>
  6. #include<algorithm>
  7. #include<map>
  8. #include<queue>
  9. #include<vector>
  10. #include<cmath>
  11. #include<utility>
  12. using namespace std;
  13. typedef long long LL;
  14. const int N = 100008, INF = 0x3F3F3F3F;
  15. #define MS(a, num) memset(a, num, sizeof(a))
  16. #define PB(A) push_back(A)
  17. #define FOR(i, n) for(int i = 0; i < n; i++)
  18.  
  19. int dfn[N][2];
  20. int fa[N];
  21. int son[N][2], des[N];
  22. struct Node{
  23. int to,next;
  24. }edge[N * 2];
  25.  
  26. int head[N],tot, deg[N];
  27. int tim;
  28. void init(){
  29. memset(head, -1, sizeof(head));
  30. memset(deg, 0, sizeof(deg));
  31. tot = 0;
  32. }
  33. void add(int u, int to){
  34. edge[tot].to=to;
  35. edge[tot].next=head[u];
  36. deg[u]++;
  37. head[u]=tot++;
  38. }
  39.  
  40. void dfs(int u, int f){
  41. fa[u] = f;
  42. dfn[u][0] = tim++;
  43.  
  44. son[u][0] = INF;
  45. son[u][1] = INF;
  46. des[u] = INF;
  47. for(int i = head[u]; ~i ; i = edge[i].next){
  48. int v = edge[i].to;
  49. if(v != f){
  50. dfs(v, u);
  51. son[u][1] = min(son[u][1], v);
  52. if(son[u][0] > son[u][1]){
  53. swap(son[u][0], son[u][1]);
  54. }
  55. des[u] = min(des[u], v);
  56. des[u] = min(des[u], des[v]);
  57. }
  58. }
  59. dfn[u][1] = tim++;
  60. }
  61.  
  62. bool isFa(int x, int y){
  63. if(dfn[x][0] <= dfn[y][0] && dfn[x][1] >= dfn[y][0]){
  64. return true;
  65. }
  66. return false;
  67. }
  68.  
  69. int main(){
  70. int t;
  71. cin>>t;
  72. while(t--){
  73. int n, q;
  74. scanf("%d %d", &n, &q);
  75. init();
  76. for(int i = 0; i < n - 1; i++){
  77. int u, v;
  78. scanf("%d %d", &u, &v);
  79. add(u, v);
  80. add(v, u);
  81. }
  82. tim = 0;
  83. dfs(1, INF);//1号节点父亲注意要为NF,便于处理
  84.  
  85. int des2 = INF;//1号节点子树后继次小值
  86. int minv = INF;//判断1号节点子树后继最小值从哪个儿子节点发出
  87. for(int i = head[1]; ~i; i = edge[i].next){
  88. int v = edge[i].to;
  89. int tp = min(v, des[v]);
  90. if(tp != des[1] && tp < des2){
  91. des2 = tp;
  92. }
  93. if(tp == des[1]){
  94. minv = v;
  95. }
  96. }
  97.  
  98. while(q--){
  99. int x, y;
  100. scanf("%d %d", &x, &y);
  101. if(deg[y] == 1){
  102. printf("no answers!\n");
  103. continue;
  104. }
  105. if(isFa(y, x)){//x在y子树范围内(以1为根时)
  106. int mson, mdes;
  107. if(isFa(son[y][0], x)){
  108. mson = min(son[y][1], fa[y]);
  109. }else{
  110. mson = min(son[y][0], fa[y]);
  111. }
  112.  
  113. if(y != 1){
  114. mdes = 1;
  115. }else{
  116. //y不是节点1,要判断
  117. if(isFa(minv, x)){
  118. mdes = des2;
  119. }else{
  120. mdes = des[y];
  121. }
  122. }
  123. printf("%d %d\n", mson, mdes);
  124.  
  125. }else{
  126. //x不在y子树范围内(以1为根时),直接输出
  127. printf("%d %d\n", son[y][0], des[y]);
  128. }
  129. }
  130. printf("\n");
  131. }
  132.  
  133. return 0;
  134. }

  

HDU4008 Parent and son(树形DP LCA)的更多相关文章

  1. poj3417 Network 树形Dp+LCA

    题意:给定一棵n个节点的树,然后在给定m条边,去掉m条边中的一条和原树中的一条边,使得树至少分为两部分,问有多少种方案. 神题,一点也想不到做法, 首先要分析出加入一条边之后会形成环,形成环的话,如果 ...

  2. hdu_5293_Tree chain problem(DFS序+树形DP+LCA)

    题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=5293 被这题打蹦了,看着题解写的,很是爆炸,确实想不到,我用的DFS序+LCA+树形DP,当然也可以写 ...

  3. poj 3417 树形dp+LCA

    思路:我以前一直喜欢用根号n分段的LCA.在这题上挂了,第一次发现这样的LCA被卡.果断改用Tarjan离线算法求LCA. 当前节点为u,其子节点为v.那么: 当以v根的子树中含有连接子树以外点的边数 ...

  4. POJ 3728 The merchant (树形DP+LCA)

    题目:https://vjudge.net/contest/323605#problem/E 题意:一棵n个点的树,然后有m个查询,每次查询找(u->v)路径上的两个数,a[i],a[j],(i ...

  5. Codeforces Round #343 (Div. 2) E. Famil Door and Roads (树形dp,lca)

    Famil Door's City map looks like a tree (undirected connected acyclic graph) so other people call it ...

  6. HDU 4008 Parent and son

    树形DP+LCA+思路.这题可真是有点难度......所以准备详细写一下题解. 题意:给一颗无根树,有Q次询问,每次询问指定一个根节点X,然后让你计算Y节点的儿子和子孙中,编号最小的节点是多少. 我们 ...

  7. P2495 [SDOI2011]消耗战 lca倍增+虚树+树形dp

    题目:给出n个点的树  q次询问  问切断 k个点(不和1号点联通)的最小代价是多少 思路:树形dp  sum[i]表示切断i的子树中需要切断的点的最小代价是多少 mi[i]表示1--i中的最小边权 ...

  8. BZOJ_2286_[Sdoi2011]消耗战_虚树+树形DP+树剖lca

    BZOJ_2286_[Sdoi2011]消耗战_虚树+树形DP Description 在一场战争中,战场由n个岛屿和n-1个桥梁组成,保证每两个岛屿间有且仅有一条路径可达.现在,我军已经侦查到敌军的 ...

  9. poj3417 LCA + 树形dp

    Network Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 4478   Accepted: 1292 Descripti ...

随机推荐

  1. C#调用有有参有返的存储过程

    (1)在SQL Server中建立如下的存储过程: set ANSI_NULLS ONset QUOTED_IDENTIFIER ONGOCREATE PROCEDURE [dbo].[GetName ...

  2. discuz论坛移植修改数据库配置

    从其他地方拷贝的discuz源码,可能需要修改数据库配置 分别打开discuz目录下面以下三个文件 discuzRoot/uc_server/data/config.inc.phpdiscuzRoot ...

  3. 用批处理启动MySQL命令行工具

    最近在看MySQL,安装好之后,每次在开始菜单去启动MySQL命令行工具的时候,都是直接用root用户连接我本地的数据库 输入密码开始工作,但是要连接服务器上的MySQL的话,就要去CMD下运行 : ...

  4. sharepoint---RBS回收站清空设置

    默认天数 :

  5. ssh免密码登陆设置

    服务器端 CentOS 6.5下编辑/etc/ssh/sshd_config MacOSx下编辑/etc/sshd_config #开启公钥验证 RSAAuthentication yes Pubke ...

  6. git命令使用

    2015-07-15 11:59:11 git pull : 相当于 SVN up git status : 相当于 SVN st git add a.txt: 新添加文件 或者 将文件修改保存到索引 ...

  7. Mybatis中的in查询和foreach标签

    Mybatis中的foreach的主要用在构建in条件中,它可以在SQL语句中进行迭代一个集合. foreach元素的属性主要有 item,index,collection,open,separato ...

  8. cxGrid 速度

    在做AdoHelper实用程序的时候,我用了DevExpress的cxGrid控件.在此之前用的是dbgrid,考虑到不能把所有的数据都拉到本地,我用了动态生成的select top 500的命令.这 ...

  9. 4.js模式-发布-订阅模式

    1. 发布-订阅模式 var observe = (function(){ var events = {}, listen, trigger, remmove; listen = function(k ...

  10. 8. javacript高级程序设计-BOM

    1. BOM 1.1 window BOM的核心对象是window,它表示浏览器的一个实例.在浏览器中,window对象有双重身份, 1.1.1 全局作用域 由于window对象同时扮演着ECMASc ...