一棵树(根节点是 1),给出两个集合,集合是 由树上的节点组成的。从两个集合中分别选一个元素,求出他们的 lca,问:lca 的深度最大是多少。
每个询问,两个集合,建虚树,然后dfs一遍,记录子树有没有A点、有没有B点,然后看既有A点又有B点的就更新深度到答案。
#include <bits/stdc++.h>
using namespace std;
const int maxN=100000+10;
const int maxM=100000+10;
const int max_log_n=21;
int n,m,Head[maxN],eg[maxM<<1],nxt[maxM<<1],tot=0;
void init() {
memset(Head,0,sizeof(Head)); memset(eg,0,sizeof(eg)); memset(nxt,0,sizeof(nxt)); tot=0;
}
void addEdge(int u,int v) {
eg[++tot]=v; nxt[tot]=Head[u]; Head[u]=tot;
eg[++tot]=u; nxt[tot]=Head[v]; Head[v]=tot;
}
int id[maxN],dfsclock=0,pa[max_log_n][maxN],dep[maxN];
void dfs(int v,int fa) {
id[v]=++dfsclock;
int k=1;
pa[0][v]=fa;
dep[v]=fa==-1?1:dep[fa]+1;
while(pa[k-1][v]!=-1) {
pa[k][v]=pa[k-1][pa[k-1][v]];
k++;
}
for(int i=Head[v];i;i=nxt[i]) {
int u=eg[i];
if(u!=fa) dfs(u,v);
}
}
int getLca(int u,int v) {
if(dep[u]>dep[v]) swap(u,v);
for(int k=max_log_n-1;k>=0;k--) {
if(((dep[v]-dep[u])>>k)&1) v=pa[k][v];
}
if(u==v) return u;
for(int k=max_log_n-1;k>=0;k--) {
if(pa[k][v]!=pa[k][u]) v=pa[k][v],u=pa[k][u];
}
return pa[0][v];
}
vector<int > As,Bs,all;
bool A[maxN],B[maxN];
bool cmp_by_id(int A,int B) {
return id[A]<id[B];
}
vector<int > g[maxN];
bool recEg[maxN];
vector<int > used;
void new_addEdge(int u,int v) {
g[u].push_back(v); g[v].push_back(u);
if(!recEg[v]) used.push_back(v),recEg[v]=true;
if(!recEg[u]) used.push_back(u),recEg[u]=true;
}
int stk[maxN],tp=0;
int ans=0;
bool havA[maxN],havB[maxN],vis[maxN];
void Recor(int v,int fa) {
if(A[v]) havA[v]=true;
if(B[v]) havB[v]=true;
for(int i=0;i<(int)g[v].size();i++) {
int u=g[v][i];
if(u!=fa) Recor(u,v),havA[v]|=havA[u],havB[v]|=havB[u];
}
if(havA[v] && havB[v]) ans=max(ans,dep[v]);
}
int main() {
int k,x;
while(scanf("%d%d",&n,&m)==2) {
init();
memset(pa,-1,sizeof(pa)); memset(dep,0,sizeof(dep));
memset(id,0,sizeof(id)); dfsclock=0;
int u,v;
for(int i=1;i<=n-1;i++) {
scanf("%d%d",&u,&v);
addEdge(u,v);
}
dfs(1,-1);
for(int z=0;z<m;z++) {
scanf("%d",&k);
for(int i=1;i<=k;i++) {
scanf("%d",&x);
A[x]=true; As.push_back(x);
if(!vis[x]) all.push_back(x);
vis[x]=true;
}
scanf("%d",&k);
for(int i=1;i<=k;i++) {
scanf("%d",&x);
B[x]=true; Bs.push_back(x);
if(!vis[x]) all.push_back(x);
vis[x]=true;
}
sort(all.begin(),all.end(),cmp_by_id);
tp=0;
stk[++tp]=1;
for(int i=0;i<(int)all.size();i++) {
int lca=getLca(stk[tp],all[i]);
if(lca==stk[tp]) stk[++tp]=all[i];
else {
while(tp>=2 && dep[stk[tp-1]]>=dep[lca]) new_addEdge(stk[tp],stk[tp-1]),tp--;
if(lca!=stk[tp]) new_addEdge(stk[tp],lca);
tp--;
stk[++tp]=lca; stk[++tp]=all[i];
}
}
while(tp-1) new_addEdge(stk[tp],stk[tp-1]),tp--;
ans=0;
Recor(1,-1);
printf("%d\n",ans);
for(int i=0;i<(int)As.size();i++) A[As[i]]=false;
for(int i=0;i<(int)Bs.size();i++) B[Bs[i]]=false;
As.clear(); Bs.clear();
for(int i=0;i<(int)all.size();i++) vis[all[i]]=false;
all.clear();
for(int i=0;i<(int)used.size();i++) {
recEg[used[i]]=false,g[used[i]].clear();
havA[used[i]]=false,havB[used[i]]=false;
}
used.clear();
}
}
return 0;
}
原文地址:https://www.cnblogs.com/darkroome/p/9198553.html
时间: 2024-11-10 11:54:27