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

  

原文地址:https://www.cnblogs.com/guangheli/p/13037986.html