1. 程式人生 > >hdu 6031 Innumerable Ancestors (虛樹 lca)

hdu 6031 Innumerable Ancestors (虛樹 lca)

als href sin cpp end HA rabl AD gin

hdu6031

一棵樹(根節點是 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; }

hdu 6031 Innumerable Ancestors (虛樹 lca)