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

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

#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
#include<queue>
#include<vector>
#include<cmath>
#include<utility>
using namespace std;
typedef long long LL;
const int N = 100008, INF = 0x3F3F3F3F;
#define MS(a, num) memset(a, num, sizeof(a))
#define PB(A) push_back(A)
#define FOR(i, n) for(int i = 0; i < n; i++) int dfn[N][2];
int fa[N];
int son[N][2], des[N];
struct Node{
int to,next;
}edge[N * 2]; int head[N],tot, deg[N];
int tim;
void init(){
memset(head, -1, sizeof(head));
memset(deg, 0, sizeof(deg));
tot = 0;
}
void add(int u, int to){
edge[tot].to=to;
edge[tot].next=head[u];
deg[u]++;
head[u]=tot++;
} void dfs(int u, int f){
fa[u] = f;
dfn[u][0] = tim++; son[u][0] = INF;
son[u][1] = INF;
des[u] = INF;
for(int i = head[u]; ~i ; i = edge[i].next){
int v = edge[i].to;
if(v != f){
dfs(v, u);
son[u][1] = min(son[u][1], v);
if(son[u][0] > son[u][1]){
swap(son[u][0], son[u][1]);
}
des[u] = min(des[u], v);
des[u] = min(des[u], des[v]);
}
}
dfn[u][1] = tim++;
} bool isFa(int x, int y){
if(dfn[x][0] <= dfn[y][0] && dfn[x][1] >= dfn[y][0]){
return true;
}
return false;
} int main(){
int t;
cin>>t;
while(t--){
int n, q;
scanf("%d %d", &n, &q);
init();
for(int i = 0; i < n - 1; i++){
int u, v;
scanf("%d %d", &u, &v);
add(u, v);
add(v, u);
}
tim = 0;
dfs(1, INF);//1号节点父亲注意要为NF,便于处理 int des2 = INF;//1号节点子树后继次小值
int minv = INF;//判断1号节点子树后继最小值从哪个儿子节点发出
for(int i = head[1]; ~i; i = edge[i].next){
int v = edge[i].to;
int tp = min(v, des[v]);
if(tp != des[1] && tp < des2){
des2 = tp;
}
if(tp == des[1]){
minv = v;
}
} while(q--){
int x, y;
scanf("%d %d", &x, &y);
if(deg[y] == 1){
printf("no answers!\n");
continue;
}
if(isFa(y, x)){//x在y子树范围内(以1为根时)
int mson, mdes;
if(isFa(son[y][0], x)){
mson = min(son[y][1], fa[y]);
}else{
mson = min(son[y][0], fa[y]);
} if(y != 1){
mdes = 1;
}else{
//y不是节点1,要判断
if(isFa(minv, x)){
mdes = des2;
}else{
mdes = des[y];
}
}
printf("%d %d\n", mson, mdes); }else{
//x不在y子树范围内(以1为根时),直接输出
printf("%d %d\n", son[y][0], des[y]);
}
}
printf("\n");
} return 0;
}

  

最新文章

  1. objective-c 语法快速过(5)
  2. 可分组的选择框控件(MVVM下)(Toggle样式 仿造单选框RadioButton,复选框CheckBox功能)
  3. Exception异常
  4. 手机端touchstart,touchmove,touchend事件,优化用户划入某个可以点击LI的效果
  5. Android之多线程断点下载
  6. VB调用控制面板
  7. utf-8转换为ansi和修改文件名的批处理(可解决source insight中文注释乱码问题)
  8. 【离线】【深搜】【树】Codeforces 707D Persistent Bookcase
  9. 最大子数组分治方案C++实现
  10. go 开发环境安装教程 windows
  11. Python调用ansible API系列(五)综合使用
  12. shiro认证登录实现
  13. 2018最新iOS端界面UI设计规范整理
  14. Luogu P3959 宝藏
  15. NATS—协议详解(nats-protocol)
  16. Linux基础命令---zip
  17. ERROR 2059 (HY000): Authentication plugin &#39;caching_sha2_password&#39; cannot be loaded
  18. LeetCode141:Linked List Cycle
  19. dorado7-HelloWorld
  20. Oracle.ManagedDataAccess.dll方式操作oracle数据库

热门文章

  1. Python自动化之sqlalchemy关联查询
  2. 再谈Weiphp公众平台开发——1、增加插件
  3. UOJ 做题记录
  4. Sublime text2 插件推荐
  5. Spring boot 打成jar包问题总结
  6. AutoMapper Getting started
  7. Expression表达式树
  8. 怎样将myeclipse里默认编码设置成utf-8
  9. Javascript调用C#后台方法及JSon解析
  10. 3.UNION