zoukankan      html  css  js  c++  java
  • 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; 
    }
    

      

  • 相关阅读:
    linux端口开放指定端口的两种方法
    关于JqueryCheck选中获取数据
    ASP.NET MVC 简单分页代码
    ASP.NET MVC4分页Site.CSS
    SQL索引的优缺点
    SQL字段数据类型小技巧
    数据库强制完整性的机制
    WinFrom饼形图
    WinFrom折线图
    WinFrom柱形图
  • 原文地址:https://www.cnblogs.com/guangheli/p/13037986.html
Copyright © 2011-2022 走看看