题意:

给定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. JSP(2) - JSP指令 - 小易Java笔记

    JSP指令是给JSP引擎用的,即给服务器用的.作用是告诉服务器,该如何处理JSP中除了指令之外的内容.包括page.include.taglib三种 基本的语法格式:<%@ 指令名称 属性1=& ...

  2. SSH的简单入门体验(Struts2.1+Spring3.1+Hibernate4.1)- 查询系统(下)

    我们继续吧,SSH最大的优点就是实现的系统的松耦合,能够将后台和前台有机的分离开来. 一.目录结构 一个好的程序要有一个好的开始.我们先来看看整个目录结构吧 主要的是三层架构概念,或者说是mvc的概念 ...

  3. css左右箭头

    .record-left{ content: ""; width: 0; height: 0; float: left; border-top: 10px solid transp ...

  4. JVM垃圾收集规则和算法

    1.垃圾收集 Garbage Collection 程序计数器.虚拟机栈.本地方法栈这三部分内存随着线程生而生,随着线程灭而自然的回收,他们的大小在编译期间就大致确定了下来,所以对这部分的回收是具备确 ...

  5. python multiprocessing多进程模块

    原文:https://blog.csdn.net/CityzenOldwang/article/details/78584175 多进程 Multiprocessing 模块 multiprocess ...

  6. mysql union用法代码示例

    MYSQL UNION 操作符 UNION 操作符用于合并两个或多个 SELECT 语句的结果集. 请注意,UNION 内部的 SELECT 语句必须拥有相同数量的列.列也必须拥有相似的数据类型.同时 ...

  7. sublime text3插件TrailingSpaces无法使用的解决方法

    TrailingSpaces是很好用的一款插件,可以清除代码结尾打多了几个空格或Tab,对于代码洁癖绝对是个福音,我的sublime text3本来安装了这款插件,也可以正常使用,今天突然不能用了,即 ...

  8. POJ 2387 链式前向星下的SPFA

    (POJ)[http://poj.org/problem?id=2387] Til the Cows Come Home Time Limit: 1000MS Memory Limit: 65536K ...

  9. log4j笔记:升级2.X版本的日志滚动问题

    因为slf4j依赖的log4j在流量大的时候总遇到多线程引起的死锁问题,升级到log4j2.x版本.原来的log4j.properties配置文件已经不被log4j2支持了,需要改写为log4j2.x ...

  10. CodeForces - 981E Addition on Segments

    考虑每个点i在什么情况下会成为最大值. 当选的区间子集是 包含i的区间的一个子集的时候,i肯定会是最大值. 所以我们就可以用这种方法得到所有点的可能的最大值是多少... 也就是说,最后的局面可以仅由一 ...