There is a tree having n nodes, labeled from 1 to n. The root of the tree is always 1, and the depth of a node p is the number of nodes on the shortest path between node p and the root.
In computer science, the Lowest Common Ancestor (LCA) of two nodes v and w in a tree is the lowest (i.e. deepest) node that has both v and w as descendants, where we define each node to be a descendant of itself (so if v has a direct connection from w, w is the lowest common ancestor).
You have to answer m queries. Each query gives two non-empty node sets A and B, there might be some nodes in both sets.
You should select one node x from set A, and one node y from set B, x and y can be the same node. Your goal is to maximize the depth of the LCA of x and y.
Please write a program to answer these queries.
给定 N 节点的树,问集合 A 中节点 x 与集合 B 中节点 y 的 LCA(x, y) 的深度的最大值。
根据 DFS 序,若两个点的 DFS 序越接近,则两个点的 LCA 的深度越大。
故可将集合 A 与集合 B 中的点分别按照 DFS 序排序。遍历集合 A 中所有元素,对任意一个元素 x,在集合 B 中二分查找与其 DFS 序最接近的点 y1, y2 (DFS 序大于等于 x 及 DFS 序小于 x)。利用 LCA 算法 O(logN) 求取 LCA(x, y1) , LCA(x, y2) ,并取深度的最大值即可。
#include
using namespace std;
const int N = 100000 + 10;
const int maxh = 20; //log2(N);
struct Edge {
int to, nxt;
} e[N*2];
int head[N], cnt;
void addedge(int u, int v) {
e[++cnt].nxt = head[u];
e[cnt].to = v;
head[u] = cnt;
}
int id[N], idx, a[N], b[N], n, m;
void genId(int rt, int pre) {
id[rt] = ++idx;
for(int i=head[rt];i;i=e[i].nxt) {
if(e[i].to == pre) continue;
genId(e[i].to, rt);
}
}
bool cmp(int a, int b) {
return id[a] < id[b];
}
int dep[N], anc[N][20];
void dfs(int rt) {
static int Stack[N];
int top = 0;
dep[rt] = 1;
for(int i=0;iwhile(top) {
int x = Stack[top];
if(x != rt) {
for(int i=1, y;i1], anc[x][i] = anc[y][i-1];
}
for(int &i=head[x];i;i=e[i].nxt) {
int y = e[i].to;
if(y != anc[x][0]) {
dep[y] = dep[x] + 1;
anc[y][0] = x;
Stack[++top] = y;
}
}
while(top && head[Stack[top]] == 0) top--;
}
}
void swim(int &x, int H) {
for(int i=0;H;i++) {
if(H & 1) x = anc[x][i];
H /= 2;
}
}
int lca(int x, int y) {
int i;
if(dep[x] > dep[y]) swap(x, y);
swim(y, dep[y]-dep[x]);
if(x == y) return x;
for(;;) {
for(i=0;anc[x][i] != anc[y][i];i++);
if(i == 0) return anc[x][0];
x = anc[x][i-1];
y = anc[y][i-1];
}
return -1;
}
void init() {
memset(head, 0, sizeof(head));
cnt = 0; idx = 0;
}
int main()
{
while(scanf("%d %d", &n, &m)!=EOF)
{
init();
for(int i=1, u, v;iscanf("%d %d",&u,&v),
addedge(u, v),
addedge(v, u);
genId(1, -1);
dfs(1);
for(int i=1, ka, kb;i<=m;i++)
{
scanf("%d",&ka);
for(int j=0;jscanf("%d",&a[j]);
sort(a, a+ka, cmp);
scanf("%d",&kb);
for(int j=0;jscanf("%d",&b[j]);
sort(b, b+kb, cmp);
int ans = 0;
for(int j=0, pos;jif(pos < kb)
ans = max(ans, dep[lca(a[j], b[pos])]);
if(--pos >= 0)
ans = max(ans, dep[lca(a[j], b[pos])]);
}
printf("%d\n", ans);
}
}
}