先记录以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; }
时间: 2024-10-12 15:24:38