• bzoj1787: [Ahoi2008]Meet 紧急集合


    lca。

    3个点分别lca,可以知道,深度最深的lca就是答案。

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    const int maxn = 500000 + 10;
    const int maxm = 1000000 + 10;
    const int maxl = 22;
    
    int g[maxn],v[maxm],next[maxm],eid;
    int anc[maxn][maxl],h[maxn];
    int q[maxn];
    int A,B,C,n,m;
    
    void addedge(int a,int b) {
        v[eid]=b; next[eid]=g[a]; g[a]=eid++;
        v[eid]=a; next[eid]=g[b]; g[b]=eid++;
    }
    
    void build() {
        scanf("%d%d",&n,&m);
        memset(g,-1,sizeof(g));
        for(int i=1,u,v;i<n;i++) {
            scanf("%d%d",&u,&v);
            addedge(u,v);
        }    
    }
    
    void bfs() {
        int l,r,u;
        l=r=0;
        h[1]=1;q[r++]=1; anc[1][0]=1;
        while(l<r) {
            u=q[l++];
            for(int i=g[u];~i;i=next[i]) if(v[i]!=anc[u][0]) {
                anc[v[i]][0]=u;
                q[r++]=v[i];    
                h[v[i]]=h[u]+1;
            }
        }
    }
    
    void up(int &a,int H) {
        for(int i=maxl-1;i>=0;i--) 
            if(h[anc[a][i]]>=H) a=anc[a][i];
    }
    
    int LCA(int a,int b) {
        if(h[a]!=h[b]) {
            if(h[a]>h[b]) up(a,h[b]);
            else up(b,h[a]);    
        }
        if(a==b) return a;
        for(int l=maxl-1;l>=0;l--) 
            if(anc[a][l]!=anc[b][l]) {
                a=anc[a][l];
                b=anc[b][l];    
            }
        return anc[a][0];
    }
    
    int dis(int a,int b) {
        int p=LCA(a,b);
        return h[a]+h[b]-2*h[p];
    }
    
    void solve() {
        for(int i=1;i<=m;i++) {
            int p,p1,p2,p3;
            scanf("%d%d%d",&A,&B,&C);
            p1=LCA(A,B),p2=LCA(A,C),p3=LCA(B,C);
            if(p1==p2) p=p3;
            else if(p1==p3) p=p2;
            else p=p1;
            printf("%d %d
    ",p,dis(p,A)+dis(p,B)+dis(p,C));    
        }
    }
    
    
    void predo() {
        bfs();    
        for(int i=1;i<maxl;i++) 
        for(int u=1;u<=n;u++) 
            anc[u][i]=anc[anc[u][i-1]][i-1];
    }
    
    int main() {
        build();
        predo();
        solve();
        return 0;
    }
  • 相关阅读:
    多项式回归学习笔记
    线性回归学习笔记
    CentOS6.9下安装python notebook
    CentOS 6.9下安装PostgreSQL
    区块链共识机制及其迭代
    比特币的区块结构解析
    区块链学习路线
    应用缓存的常见问题及解决
    阿里巴巴开源技术体系
    工程师进阶推荐十本书
  • 原文地址:https://www.cnblogs.com/invoid/p/5571606.html
Copyright © 2020-2023  润新知