HDU 4008 Parent and son LCA+树形dp
题意:
给定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的更多相关文章
- HDU 4008 Parent and son
树形DP+LCA+思路.这题可真是有点难度......所以准备详细写一下题解. 题意:给一颗无根树,有Q次询问,每次询问指定一个根节点X,然后让你计算Y节点的儿子和子孙中,编号最小的节点是多少. 我们 ...
- 可恶!学了这么久的LCA,联考的题目却是LCA+树形DP!!!可恶|!!!这几天想学学树形DP吧!先来一道入门题HDU 1520 Anniversary party
题目描述 某大学有N个职员,编号为1~N.他们之间有从属关系,也就是说他们的关系就像一棵以校长为根的树,父结点就是子结点的直接上司.现在有个周年庆宴会,宴会每邀请来一个职员都会增加一定的快乐指数Ri, ...
- poj3417 LCA + 树形dp
Network Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 4478 Accepted: 1292 Descripti ...
- HDU 1054 Strategic Game(最小点覆盖+树形dp)
题目链接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=106048#problem/B 题意:给出一些点相连,找出最小的点数覆盖所有的 ...
- HDU 1520.Anniversary party 基础的树形dp
Anniversary party Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others ...
- HDU 5977 Garden of Eden (树形dp+快速沃尔什变换FWT)
CGZ大佬提醒我,我要是再不更博客可就连一月一更的频率也没有了... emmm,正好做了一道有点意思的题,就拿出来充数吧=.= 题意 一棵树,有 $ n (n\leq50000) $ 个节点,每个点都 ...
- HDU 3586 Information Disturbing(二分+树形dp)
http://acm.split.hdu.edu.cn/showproblem.php?pid=3586 题意: 给定一个带权无向树,要切断所有叶子节点和1号节点(总根)的联系,每次切断边的费用不能超 ...
- HDU 5682 zxa and leaf 二分 树形dp
zxa and leaf 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5682 Description zxa have an unrooted t ...
- HDU 6201 2017沈阳网络赛 树形DP或者SPFA最长路
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6201 题意:给出一棵树,每个点有一个权值,代表商品的售价,树上每一条边上也有一个权值,代表从这条边经过 ...
随机推荐
- 【C++】this指针
来自:黄邦勇帅 this 指针是所有成员函数的隐含指针,每次调用成员函数时,this 指针就指向调用此函数的对象.可以在成员函数类 部使用显使用this 指针. 友元函数不是类的成员函数,所以友元函数 ...
- 《Java编程思想》笔记 第十章 内部类
1.创建内部类对象 创建内部类对象(相当于new内部类对象) 外围类对象.new 内部类( ). 创建内部类对象一种方法是 外围类有一个方法返回内部类对象. 没有外围类对象就不能创建内部类对象,因为内 ...
- mysql-5.7.15-winx64配置
1. 配置环境变量 1.1 添加path路径 选择 控制面板>系统和安全>系统>高级系统设置>环境变量 mysql文件目录的绝对路径\bin 1.2 修改mysql ...
- MATLAB规划问题——线性规划和非线性规划
1.线性规划 求线性规划问题的最优解有两种方法,一种方法是使用linprog命令,另一种是使用optimtool工具箱,下面分别介绍这两种方法. ①linprog命令 一般情况下,Linprog命令的 ...
- 【cocos2d-js官方文档】四、基础数据类型
基础数据类型统一通过方法来创建.不再支持new方式 1.坐标cc.Point 一共3种创建方式 结构:{x:0,y:0} //1 快捷创建,返回相当于cc.p(0,0) var point1 = cc ...
- django + dropzone.js 上传文件
1.dropzone.js http://www.dropzonejs.com/ dropzone.js是一个可预览\可定制化的文件拖拽上传,实现AJAX异步上传文件的工具 2.dropzone.js ...
- luogu P1359会议
//以一号节点为根节点,求出所有节点到根结点的距离,以及所有点的子节点的个数 //然后计算根据已知信息计算所有节点到当前结点的距离 //然后扫描n个点,O(n)求解 #include<bits/ ...
- 传统路径导出 VS 直接路径导出(oracle exp direct=y)
Oracle 传统的Export与Import依旧被保留到11g,而且9i与10g有很多依旧使用Export与Import方式进行备份与恢复的企业.从Oracle 7.3开始,传统的exp导出程序提供 ...
- 【找规律】Codeforces Round #392 (Div. 2) C. Unfair Poll
C. Unfair Poll time limit per test 1 second memory limit per test 256 megabytes input standard input ...
- 【暴力】洛谷 P2038 NOIP2014提高组 day2 T1 无线网络发射器选址
暴力枚举. #include<cstdio> #include<algorithm> using namespace std; ][],d,n,x,y,z,num,ans=-; ...