BZOJ5479: tree LCA+DFS序
手完一下发现对于两个点求 LCA 来说,最优策略是对于 DFS 序相近的两个点去求.
所以把所有点按照 DFS 序排序,然后相邻两个依次求一下就行了.
code:
#include <bits/stdc++.h> #define ll long long #define N 100007 #define setIO(s) freopen(s".in","r",stdin) using namespace std; int n,m,edges,tim; int hd[N],to[N<<1],nex[N<<1],dfn[N],dep[N],son[N],size[N],top[N],fa[N]; void add(int u,int v) { nex[++edges]=hd[u],hd[u]=edges,to[edges]=v; } void dfs(int x,int ff) { dfn[x]=++tim,dep[x]=dep[ff]+1,size[x]=1,fa[x]=ff; for(int i=hd[x];i;i=nex[i]) if(to[i]!=ff) { dfs(to[i],x); size[x]+=size[to[i]]; if(size[to[i]]>size[son[x]]) son[x]=to[i]; } } void dfs2(int x,int tp) { top[x]=tp; if(son[x]) dfs2(son[x],tp); for(int i=hd[x];i;i=nex[i]) if(to[i]!=son[x]&&to[i]!=fa[x]) dfs2(to[i],to[i]); } int LCA(int x,int y) { while(top[x]!=top[y]) dep[top[x]]>dep[top[y]]?x=fa[top[x]]:y=fa[top[y]]; return dep[x]<dep[y]?x:y; } struct data { int x,col; bool operator<(const data b) const { return dfn[x]<dfn[b.x]; } }ar[N<<1]; void calc() { int ca,cb,cn=0,ans=0; scanf("%d",&ca); for(int i=1;i<=ca;++i) ++cn,scanf("%d",&ar[cn].x),ar[cn].col=1; scanf("%d",&cb); for(int i=1;i<=cb;++i) ++cn,scanf("%d",&ar[cn].x),ar[cn].col=2; sort(ar+1,ar+1+cn); for(int i=1;i<cn;++i) if(ar[i].col!=ar[i+1].col) ans=max(ans,dep[LCA(ar[i].x,ar[i+1].x)]); printf("%d\n",ans); } void solve() { int x,y; scanf("%d%d",&n,&m); for(int i=1;i<n;++i) scanf("%d%d",&x,&y),add(x,y),add(y,x); dfs(1,0),dfs2(1,1); for(int i=1;i<=m;++i) calc(); for(int i=1;i<=n;++i) size[i]=son[i]=top[i]=dfn[i]=hd[i]=dep[i]=fa[i]=0; for(int i=1;i<=edges;++i) to[i]=nex[i]=0; edges=tim=0; } int main() { // setIO("input"); int T; scanf("%d",&T); while(T--) solve(); return 0; }