[BZOJ1787] [Ahoi2008]Meet 紧急集合

Posted Neworld2002

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[BZOJ1787] [Ahoi2008]Meet 紧急集合相关的知识,希望对你有一定的参考价值。

友链

Description


技术分享图片

技术分享图片

技术分享图片

Examples


input

6 4 
1 2 
2 3 
2 4 
4 5 
5 6 
4 5 6 
6 3 1 
2 4 4 
6 6 6 

output

5 2 
2 5 
4 1 
6 0 

Solution

两两算出LCA,有两个LCA是相同的,选择另一个作为答案

这道题似乎卡常数

#include <cstdio>
#include <cstring>
#include <algorithm>
#define MAXN 500005

int head[MAXN];
int anc[20][MAXN],d[MAXN];
int N,M;

struct edge{
    int v,next;
}G[MAXN<<1];

inline int read(){
    int num = 0;char ch = getchar();
    while(ch<‘0‘||ch>‘9‘)ch=getchar();
    while(ch>=‘0‘&&ch<=‘9‘)num=num*10+ch-48,ch=getchar();
    return num;
}
int tot = 0;
inline void add(int u,int v){
    G[++tot].v=v;G[tot].next=head[u];head[u]=tot;
}

inline void dfs(int u,int fa){
    for(register int i=head[u];i;i=G[i].next){
        int v = G[i].v;if(v==fa)continue;
        d[v]=d[u]+1;anc[0][v]=u;
        dfs(v,u);
    }
}

inline void find_your_relative(){
    for(register int i=1;i<=19;++i)
    for(register int j=1;j<=N;++j)
        anc[i][j] = anc[i-1][anc[i-1][j]];
}

inline int LCA(int u,int v){
    if(d[u]<d[v])std::swap(u,v);
    for(register int i=19;i>=0;i--)
        if(d[anc[i][u]]>=d[v])u=anc[i][u];
    if(u==v)return u;
    for(register int i=19;i>=0;i--)
        if(anc[i][u]!=anc[i][v])u=anc[i][u],v=anc[i][v];
    return anc[0][u];
}

inline int dis(int u,int v){
    int lca = LCA(u,v);
    return d[u]+d[v]-(d[lca]<<1);
}
int main(){
    
    
    
    N=read();M=read();
    int u,v,a;
    for(register int i=1;i<N;++i){
        u=read();v=read();
        add(u,v);add(v,u);
    }
    
    d[1]=1;anc[0][1]=0;
    dfs(1,0);
    find_your_relative();
    
    for(register int i=1;i<=M;++i){
        u=read();v=read();a=read();
        int lca_uv = LCA(u,v);
        int lca_ua = LCA(u,a);
        int lca_va = LCA(v,a);
        if(lca_uv==lca_ua)printf("%d %d\n",lca_va,d[v]+d[a]-(d[lca_va]<<1)+dis(lca_va,u));
            else if(lca_uv==lca_va)printf("%d %d\n",lca_ua,d[u]+d[a]-(d[lca_ua]<<1)+dis(lca_ua,v));
                else if(lca_ua==lca_va)printf("%d %d\n",lca_uv,d[v]+d[u]-(d[lca_uv]<<1)+dis(lca_uv,a));     
    }
    return 0;
}

 

以上是关于[BZOJ1787] [Ahoi2008]Meet 紧急集合的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ-1787: [Ahoi2008]Meet 紧急集合 (LCA)

BZOJ——1787: [Ahoi2008]Meet 紧急集合

[BZOJ1787] [Ahoi2008]Meet 紧急集合

bzoj1787: [Ahoi2008]Meet 紧急集合

bzoj1787[Ahoi2008]Meet 紧急集合

bzoj 1787: [Ahoi2008]Meet 紧急集合