题意:

给定case数

给定n个点的树,m个询问

以下n-1行给出树边

m个询问 x y

问:以x为根。y子树下 y的最小点标的儿子节点 和子孙节点

思路:

用son[u][0] 表示u的最小儿子 son[u][2] 表示u的次小儿子

son[u][1] 表示u的最小子孙

若lca(x,y)  !=y  则就是上述的答案

若lca(x,y) == y

1、y != 1 那么最小儿子就是除了x外的节点,且此时father[y] 也是y的儿子节点, 而最小的子孙节点就是1

2、y==1 那么特殊处理一下。用map维护一下除了u节点下的子树。1的最小子孙节点

#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <string>
#include <time.h>
#include <math.h>
#include <queue>
#include <stack>
#include <set>
#include <map>
using namespace std;
#define inf 1000000
#define N 100050
struct Edge{
int from, to, dis, nex;
}edge[5*N];
int head[N],edgenum,dis[N],fa[N][20],dep[N]; //fa[i][x] 是i的第2^x个父亲(假设超过范围就是根)
void add(int u,int v,int w){
Edge E={u,v,w,head[u]};
edge[edgenum] = E;
head[u]=edgenum++;
}
void bfs(int root){
queue<int> q;
fa[root][0]=root;dep[root]=0;dis[root]=0;
q.push(root);
while(!q.empty()){
int u=q.front();q.pop();
for(int i=1;i<20;i++)fa[u][i]=fa[fa[u][i-1]][i-1];
for(int i=head[u]; ~i;i=edge[i].nex){
int v=edge[i].to;if(v==fa[u][0])continue;
dep[v]=dep[u]+1;dis[v]=dis[u]+edge[i].dis;fa[v][0]=u;
q.push(v);
}
}
}
int move(int x,int y){//把x移动到y以下
int D = dep[x] - dep[y]-1;
while(D){
int z = (int)(log10(1.0*D)/log10(2.0));
x = fa[x][z];
D-=1<<z;
}
return x;
}
int Lca(int x,int y){
if(dep[x]<dep[y])swap(x,y);
for(int i=0;i<20;i++)if((dep[x]-dep[y])&(1<<i))x=fa[x][i];
if(x==y)return x;
for(int i=19;i>=0;i--)if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];
return fa[x][0];
}
void init(){memset(head, -1, sizeof head); edgenum = 0;}
int son[N][3], Fa[N];
//0是最小 1是子孙最小 2是次小
void dfs(int u,int father){
Fa[u] = father;
son[u][0] = son[u][1] = son[u][2] = inf;
for(int i = head[u]; ~i; i = edge[i].nex){
int v = edge[i].to; if(v==father)continue;
dfs(v,u);
if(v<son[u][0])
son[u][2] = son[u][0], son[u][0] = v;
else son[u][2] = min(son[u][2], v);
son[u][1] = min(son[u][1], son[v][1]);
}
son[u][1] = min(son[u][1], son[u][0]);
}
map<int,int>mp;
bool work(int x,int y){
int lca = Lca(x,y), son1, son2;
if(lca==y) {
x = move(x,y);
son1 = son[y][0];
if(son1 == x) son1 = son[y][2];
son1 = min(son1, Fa[y]);
if(y==1) {
son2 = mp[x];
}
else son2 = 1;
} else {
son1 = son[y][0];
son2 = son[y][1];
}
if(son1==inf||son2==inf)return false;
printf("%d %d\n",son1,son2);
return true;
}
int n;
int main(){
int i,j,u,v,T,que;scanf("%d",&T);
while(T--){
init();
scanf("%d %d",&n,&que);
for(i = 1; i < n; i++) {
scanf("%d %d",&u,&v);
add(u,v,1);
add(v,u,1);
}
bfs(1);
dfs(1,1);
Fa[1] = inf;
mp.clear();
int fir = inf, sec = inf;
for(i = head[1]; ~i; i = edge[i].nex){
v = edge[i].to;
mp[v] = inf;
if(v<fir)sec = fir, fir = v;
else sec = min(sec, v);
} for(i = head[1]; ~i; i = edge[i].nex){
v = edge[i].to;
if(v!=fir)mp[v] = fir;
else mp[v] = sec;
}
fir = inf; sec = inf;
for(i = head[1]; ~i; i = edge[i].nex){
v = edge[i].to;
if(son[v][1]<fir)sec = fir, fir = son[v][1];
else sec = min(sec, son[v][1]);
}
for(i = head[1]; ~i; i = edge[i].nex){
v = edge[i].to;
if(son[v][1]!=fir)
mp[v] = min(mp[v], fir);
else
mp[v] = min(mp[v], sec);
}
while(que--){
scanf("%d %d",&u,&v);
if(work(u,v)==false)
puts("no answers!");
}
puts("");
}
return 0;
}

HDU 4008 Parent and son LCA+树形dp的更多相关文章

  1. HDU 4008 Parent and son

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

  2. 可恶!学了这么久的LCA,联考的题目却是LCA+树形DP!!!可恶|!!!这几天想学学树形DP吧!先来一道入门题HDU 1520 Anniversary party

    题目描述 某大学有N个职员,编号为1~N.他们之间有从属关系,也就是说他们的关系就像一棵以校长为根的树,父结点就是子结点的直接上司.现在有个周年庆宴会,宴会每邀请来一个职员都会增加一定的快乐指数Ri, ...

  3. poj3417 LCA + 树形dp

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

  4. HDU 1054 Strategic Game(最小点覆盖+树形dp)

    题目链接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=106048#problem/B 题意:给出一些点相连,找出最小的点数覆盖所有的 ...

  5. HDU 1520.Anniversary party 基础的树形dp

    Anniversary party Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others ...

  6. HDU 5977 Garden of Eden (树形dp+快速沃尔什变换FWT)

    CGZ大佬提醒我,我要是再不更博客可就连一月一更的频率也没有了... emmm,正好做了一道有点意思的题,就拿出来充数吧=.= 题意 一棵树,有 $ n (n\leq50000) $ 个节点,每个点都 ...

  7. HDU 3586 Information Disturbing(二分+树形dp)

    http://acm.split.hdu.edu.cn/showproblem.php?pid=3586 题意: 给定一个带权无向树,要切断所有叶子节点和1号节点(总根)的联系,每次切断边的费用不能超 ...

  8. HDU 5682 zxa and leaf 二分 树形dp

    zxa and leaf 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5682 Description zxa have an unrooted t ...

  9. HDU 6201 2017沈阳网络赛 树形DP或者SPFA最长路

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6201 题意:给出一棵树,每个点有一个权值,代表商品的售价,树上每一条边上也有一个权值,代表从这条边经过 ...

随机推荐

  1. postman接口间关联

    现有A.B两个接口,A接口返回的response的body中的部分数据,是B接口发起请求部分数据的来源. A接口response的body结构如下: { "address": &q ...

  2. 【转】JSP自定义标签

    转载自:http://www.cnblogs.com/edwardlauxh/archive/2010/05/20/1918587.html tld标签的描述文件 标签的描述文件是一个描述整个标签库标 ...

  3. pygame --- 可怜的小乌龟

    来于----@小甲鱼工作室 import pygame import sys from pygame.locals import * #初始化 pygame.init() size = width,h ...

  4. SVN代码提交

    SVN代码提交(转载) 原文链接:http://www.softown.cn/post/100.html 1.SVN代码提交 1) 原则 先更新再提交: SVN是为了多人协同开发而产生的,如果你在提交 ...

  5. Python 进阶 之 traceback模块

    Traceback模块官方英文描述: Help on module traceback: NAME traceback - Extract, format and print information ...

  6. QT各个版本的下载的地址

    http://download.qt.io/archive/qt/ USE [master]GO/****** Object:  Database [BookDB]    Script Date: 0 ...

  7. [BZOJ2125]最短路(圆方树DP)

    题意:仙人掌图最短路. 算法:圆方树DP,$O(n\log n+Q\log n)$ 首先建出仙人掌圆方树(与点双圆方树的区别在于直接连割边,也就是存在圆圆边),然后考虑点u-v的最短路径,显然就是:在 ...

  8. [BZOJ 1150] 数据备份

    Link:https://www.lydsy.com/JudgeOnline/problem.php?id=1150 Solution: 思路和洛谷P1484完全相同 只不过将求最大不相邻的点权改为最 ...

  9. 洛谷 - Sdchr 的邀请赛 T1 取石子

    比赛的时候都推出来了和 质因子的指数和有关,硬是没做出来QWQ,我傻死算了 但其实这是一个结论题,因为这本来就是阶梯NIM游戏的模型.阶梯NIM游戏是指,有 n+1 阶台阶(0 ~ n),每阶上都有若 ...

  10. [LOJ6433]最大前缀和

    深刻感受到自己的水平和机房里的其他人相差甚远,他们都是随手秒这个题的... $n$很小,考虑状压DP 当一个序列在某个位置取到最大前缀和后,意味着如果把后面的数抽出来单独成序列,那么它的每个前缀和都$ ...