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;
}

浙公网安备 33010602011771号