题意: 对于给定的一棵树,树上点的数目为n,有
思路: 先对树进行剖分,然后将所有path(u,root),u∈A上的树链进行标记,并且记录该树链的最大深度。然后对于每个点v∈B,向root找到第一个被标记的树链,并返回res=MIN(mxdep[x],deep[x]),最后ans=MAX(ans,res)
总的时间复杂度为T=O(T∗(2n+2∗k∗log(n)))
#include<iostream>
#include<map>
#include<string>
#include<cstring>
#include <vector>
#include <algorithm>
#include <string.h>
#include <cstdlib>
#include <cctype>
#include <set>
#include <set>
#include <queue>
#include <stack>
#include <cstdio>
#define EPS 1e-6
using namespace std;
typedef long long ll;
typedef pair<int, int > pii;
#define sp system("pause")
const int MAXN = 110010;
struct Edge
{
int to, next;
}edge[MAXN * 2];
int head[MAXN], tot;
int top[MAXN];
int fa[MAXN];
int deep[MAXN];
int num[MAXN];
int son[MAXN];
int pos;
int mrk[MAXN];
int mxdep[MAXN];
int v[MAXN],ttt=0;
void init()
{
tot = 0;
memset(head, -1, sizeof head);
pos = 1;
memset(son, -1, sizeof son);
}
void addedge(int u, int v)
{
edge[tot].to = v;
edge[tot].next = head[u];
head[u] = tot++;
}
void dfs1(int u, int pre, int d)
{
deep[u] = d;
fa[u] = pre;
num[u] = 1;
for (int i = head[u]; i != -1; i = edge[i].next)
{
int v = edge[i].to;
if (v == pre)continue;
dfs1(v, u, d + 1);
num[u] += num[v];
if (son[u] == -1 || num[v] > num[son[u]])son[u] = v;
}
}
void dfs2(int u, int po)
{
top[u] = po;
if (son[u] == -1)return;
dfs2(son[u], po);
for (int i = head[u]; i != -1; i = edge[i].next)
{
int v = edge[i].to;
if (v != son[u] && v != fa[u])
dfs2(v, v);
}
}
int ans = 0;
void lca(int x)
{
while (x)
{
if (mrk[top[x]] == 1 && mxdep[top[x]] == deep[x])break;
mrk[top[x]] = 1;
mxdep[top[x]] = max(mxdep[top[x]], deep[x]);
x = fa[top[x]];
}
}
int lcb(int x)
{
while (!mrk[top[x]])x = fa[top[x]];
return min(mxdep[top[x]], deep[x]);
}
void clr(int x)
{
while (x)
{
if (mrk[top[x]] == 0)break;
mrk[top[x]] = 0;
mxdep[top[x]] =0;
x = fa[top[x]];
}
}
int main()
{
int n, m;
int cot = 0;
while (scanf("%d%d", &n, &m) != EOF)
{
init();
for (int i = 0; i < n - 1; i++)
{
int x, y;
scanf("%d%d", &x, &y);
addedge(x, y);
addedge(y, x);
}
dfs1(1, 0, 0);
dfs2(1, 1);
int mm = 0;
memset(mrk, 0, sizeof mrk);
memset(mxdep, 0, sizeof mxdep);
while (m--)
{
//mm++;
//if (mm >=1)break;
ttt = 0;
int x;
scanf("%d", &x);
for (int i = 0; i < x; i++)
{
int y;
scanf("%d", &y);
v[ttt++] = y;
lca(y);
}
scanf("%d", &x);
ans = 0;
for (int i = 0; i < x; i++)
{
int y;
scanf("%d", &y);
ans = max(ans, lcb(y));
}
for (int i = 0; i < ttt; i++)clr(v[i]);
printf("%d\n", ans + 1);
}
}
}