题意:

给定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. Android开发工具--AndroidStudio

    1.Android studio更改快捷键File->setttings  搜索key map就可以更改成自己喜欢的会计键风格了

  2. Asp.Net Core 项目实战参考

    Asp.Net Core 项目实战链接 http://www.cnblogs.com/fonour/p/5904530.html

  3. C#字节数组的常用解码处理方法

    在某些情况下,比如说串口通信或者读取二进制的文件,通常会得到一个byte数组形式的数据. 然而对于这个数据处理常常令人苦恼,因为通常通信情况下,并不是一个字节代表一个字符或者某个数据,而是数据夹杂在字 ...

  4. Tkinter 计算器

    from tkinter import * master = Tk() frame = Frame(master) frame.pack(padx=10,pady=10) v1 = StringVar ...

  5. Deep Learning关于Vision的Reading List

    最近开始学习深度学习了,加油! 下文转载自:http://blog.sina.com.cn/s/blog_bda0d2f10101fpp4.html 主要是顺着Bengio的PAMI review的文 ...

  6. 使用Pygame制作微信打飞机游戏PC版

    前一阵子看了一篇文章:青少年如何使用Python开始游戏开发 .看完照葫芦画瓢写了一个,觉得挺好玩儿,相当于简单学了下Pygame库.这篇文章是个12岁小孩儿写的,国外小孩儿真心NB,想我12岁的时候 ...

  7. Python 进阶 之 @property

    @property是一个装饰器,由Python原生库所支持,无需import @property 的作用是将函数变成属性,一般作用于类内的成员函数. 先贴个代码来描述一下@poperty存在的意义: ...

  8. (七)MySQL数据操作DQL:多表查询2

    (1)准备环境 1)创建员工表 mysql> create table company.employee6( -> emp_id int auto_increment primary ke ...

  9. (五)cobbler自定义系统安装

    注意:需要提前获取到物理机对应的网卡的MAC地址,例如我这里使用虚拟机进行演示 cobbler system add --name=linux-node2.com --mac=00:50:56:22: ...

  10. python提纲

    根据网上专栏整理提纲 1.模块介绍 2.time&datetime模块 3.random模块 4.os模块 5.sys模块 6.json&pickle模块 7.logging模块 8. ...