Description

给出一棵树,根节点为1

给出两个集合,集合由树上节点组成

从两个集合分别选出一个元素,求其LCA

问LCA的最大深度是多少

Input

第一行给出数据组数T

对于每组数据

第一行给出N,M,代表树的节点个数及询问次数

接下来N-1行,每行两个正整数u,v,表示u,v之间有边

接下来2M行,每两个表示一个询问

询问的第一行,第一行正整数a代表集合A中元素个数

接下来a个正整数,表示集合中的节点

询问的第二行,第一行正整数b代表集合B中元素个数

接下来b个正整数,表示集合中的节点

T<=5,N,M<=100000

sigma(a)+sigma(b)<=200000

a,b<=N

Output

对于每个询问,一行一个整数表示结果

Sample Input

1

7 3

1 2

1 3

3 4

3 5

4 6

4 7

1 6

1 7

2 6 7

1 7

2 5 4

2 3 2

Sample Output

3

4

2

Solution

考虑怎么样才会让lca的深度最大,两个点的必须尽可能相近。

那么有一个直观的贪心想法,处理出整个树的dfs序(最好树剖,因为这样会优先编号重儿子),将b数组按dfs序排序,每次对于a中的元素,在b中二分与它dfs序最接近的两个点,对lca的深度取max。

多组数据,记得清空数组。

#include <bits/stdc++.h>

#define ll long long
#define inf 0x3f3f3f3f
#define il inline namespace io { #define in(a) a=read()
#define out(a) write(a)
#define outn(a) out(a),putchar('\n') #define I_int int
inline I_int read() {
I_int x = 0 , f = 1 ; char c = getchar() ;
while( c < '0' || c > '9' ) { if( c == '-' ) f = -1 ; c = getchar() ; }
while( c >= '0' && c <= '9' ) { x = x * 10 + c - '0' ; c = getchar() ; }
return x * f ;
}
char F[ 200 ] ;
inline void write( I_int x ) {
if( x == 0 ) { putchar( '0' ) ; return ; }
I_int tmp = x > 0 ? x : -x ;
if( x < 0 ) putchar( '-' ) ;
int cnt = 0 ;
while( tmp > 0 ) {
F[ cnt ++ ] = tmp % 10 + '0' ;
tmp /= 10 ;
}
while( cnt > 0 ) putchar( F[ -- cnt ] ) ;
}
#undef I_int }
using namespace io ; using namespace std ; #define N 200010 int T;
int n, m, head[N], cnt;
struct edge {
int to, nxt;
} e[N<<1];
int fa[N], dep[N], siz[N], top[N], id[N];
int x, y;
struct Node {
int dfn, val;
}a[N], b[N]; void dfs1(int u) {
siz[u] = 1;
for(int i = head[u]; i; i = e[i].nxt) {
if(e[i].to == fa[u]) continue;
fa[e[i].to] = u;
dep[e[i].to] = dep[u] + 1;
dfs1(e[i].to);
siz[u] += siz[e[i].to];
}
} int tim = 0;
void dfs2(int u, int topf) {
id[u] = ++tim;
top[u] = topf;
int k = 0;
for(int i = head[u]; i; i = e[i].nxt) {
if(e[i].to == fa[u]) continue;
if(siz[e[i].to] > siz[k]) k = e[i].to;
}
if(!k) return;
dfs2(k, topf);
for(int i = head[u]; i; i = e[i].nxt) {
if(e[i].to == fa[u] || e[i].to == k) continue;
dfs2(e[i].to, e[i].to);
}
} int lca(int x, int y) {
while(top[x] != top[y]) {
if(dep[top[x]] < dep[top[y]]) swap(x, y);
x = fa[top[x]];
}
if(dep[x] > dep[y]) swap(x, y);
return x;
} void init() {
cnt = 0; tim = 0;
memset(head, 0, sizeof(head));
memset(dep, 0, sizeof(dep));
memset(id, 0, sizeof(id));
memset(top, 0, sizeof(top));
memset(siz, 0, sizeof(siz));
memset(fa, 0, sizeof(fa));
memset(a, 0, sizeof(a));
memset(b, 0, sizeof(b));
} void ins(int u, int v) {
e[++cnt].to = v;
e[cnt].nxt = head[u];
head[u] = cnt;
} int find(int t) {
int l = 1, r = y, ans = y;
while(l <= r) {
int mid = (l + r) >> 1;
if(b[mid].dfn >= t) ans = mid, r = mid - 1;
else l = mid + 1;
}
return ans;
} bool operator < (Node a, Node b) {
return a.dfn < b.dfn;
} int main() {
T = read();
while(T--) {
n = read(), m = read();
init();
for(int i = 1; i < n; ++i) {
int u = read(), v = read();
ins(u, v); ins(v, u);
}
dep[1] = 1;
dfs1(1); dfs2(1, 1);
while(m--) {
int ans = 0;
x = read();
for(int i = 1; i <= x; ++i) a[i].val = read(), a[i].dfn = id[a[i].val];
y = read();
for(int i = 1; i <= y; ++i) b[i].val = read(), b[i].dfn = id[b[i].val];
sort(b + 1, b + y + 1);
for(int i = 1; i <= x; ++i) {
int t = find(a[i].dfn);
ans = max(ans, dep[lca(b[t].val, a[i].val)]);
ans = max(ans, dep[lca(b[t - 1].val, a[i].val)]);
}
outn(ans);
}
}
}

BZOJ5479: tree的更多相关文章

  1. [数据结构]——二叉树(Binary Tree)、二叉搜索树(Binary Search Tree)及其衍生算法

    二叉树(Binary Tree)是最简单的树形数据结构,然而却十分精妙.其衍生出各种算法,以致于占据了数据结构的半壁江山.STL中大名顶顶的关联容器--集合(set).映射(map)便是使用二叉树实现 ...

  2. SAP CRM 树视图(TREE VIEW)

    树视图可以用于表示数据的层次. 例如:SAP CRM中的组织结构数据可以表示为树视图. 在SAP CRM Web UI的术语当中,没有像表视图(table view)或者表单视图(form view) ...

  3. 无限分级和tree结构数据增删改【提供Demo下载】

    无限分级 很多时候我们不确定等级关系的层级,这个时候就需要用到无限分级了. 说到无限分级,又要扯到递归调用了.(据说频繁递归是很耗性能的),在此我们需要先设计好表机构,用来存储无限分级的数据.当然,以 ...

  4. 2000条你应知的WPF小姿势 基础篇<45-50 Visual Tree&Logic Tree 附带两个小工具>

    在正文开始之前需要介绍一个人:Sean Sexton. 来自明尼苏达双城的软件工程师.最为出色的是他维护了两个博客:2,000Things You Should Know About C# 和 2,0 ...

  5. Leetcode 笔记 110 - Balanced Binary Tree

    题目链接:Balanced Binary Tree | LeetCode OJ Given a binary tree, determine if it is height-balanced. For ...

  6. Leetcode 笔记 100 - Same Tree

    题目链接:Same Tree | LeetCode OJ Given two binary trees, write a function to check if they are equal or ...

  7. Leetcode 笔记 99 - Recover Binary Search Tree

    题目链接:Recover Binary Search Tree | LeetCode OJ Two elements of a binary search tree (BST) are swapped ...

  8. Leetcode 笔记 98 - Validate Binary Search Tree

    题目链接:Validate Binary Search Tree | LeetCode OJ Given a binary tree, determine if it is a valid binar ...

  9. Leetcode 笔记 101 - Symmetric Tree

    题目链接:Symmetric Tree | LeetCode OJ Given a binary tree, check whether it is a mirror of itself (ie, s ...

随机推荐

  1. jQuery安装

    http://www.runoob.com/jquery/jquery-install.html 网页中添加jQuery: 方法一:可以从http://jquery.com/download/ 下载j ...

  2. codeforces 980D Perfect Groups

    题意: 有这样一个问题,给出一个数组,把里面的数字分组,使得每一个组里面的数两两相乘都是完全平方数. 问最少可以分成的组数k是多少. 现在一个人有一个数组,他想知道这个数组的连续子数组中,使得上面的问 ...

  3. django -- 修改admin 密码问题

    1.python manage.py shell 2.from django.contrib.auth.models import User 3.user=User.objects.get(usern ...

  4. 前端框架VUE----计算属性和侦听器

    一.计算属性 模板内的表达式非常便利,但是设计它们的初衷是用于简单运算的.在模板中放入太多的逻辑会让模板过重且难以维护.例如: <div> {{ message.split('').rev ...

  5. mysql数据库介绍

    一.数据库概述 二.MySql安装和基本管理 三.mysql基本语句 四.库的操作 五.表的操作 六.数据类型 七.数据类型二 八.完整性约束 九.外键的变种 三种关系 十.数据的增删改 十一.多表查 ...

  6. linux下的ifconfig命令

    ifconfig工具不仅可以被用来简单地获取网络接口配置信息,还可以修改这些配置. 1.命令格式: ifconfig [网络设备] [参数] 2.命令功能: ifconfig 命令用来查看和配置网络设 ...

  7. spring中的springSecurity安全框架的环境搭建

    首先在web.xml文件中配置监听器和过滤器 <!--监听器 加载安全框架的核心配置文件到spring容器中--> <context-param> <param-name ...

  8. django 正向,反向

    表名 ,foreignkey, 正向 obj.表名小写_set.all() 反向操作.

  9. MD5算法详解

    MD5是什么 message-digest algorithm 5(信息-摘要算法).经常说的“MD5加密”,就是它→信息-摘要算法.在下载一下东西时,经常在一些压缩包属性里,看到md5值.而且这个下 ...

  10. diff 命令实用

    1.概述 本文将要讨论的是diff命令,diff用来比较两个文件.当然文件比较的工具很多,windows系统下面就有不错的工具可以使用,例如常用的Beyond Compare,WinMerge都是图形 ...