洛谷P4281 【[AHOI2008]紧急集合 / 聚会】

LCA题目

这题不就是改成三个点的LCA吗?

首先求出三个点中两两的LCA,如果有两个LCA相等,那么三个点的LCA就是另外那对点的LCA

int fa1=lca(u,v),fa2=lca(v,w),fa3=lca(w,u);
if(fa1==fa2)printf("%d ",fa3);
if(fa2==fa3)printf("%d ",fa1);
if(fa3==fa1)printf("%d ",fa2);

最后三个点深度和减去三个LCA的深度和就是金币数

看着他这么水就马上把代码从我博客里弄下来改一改交上去

#include<bits/stdc++.h>
using namespace std;
struct edge{
    int to,next;
}ed[100005];
int n,m,u,v,w,cnt,head[50005],dep[50005],f[50005][20];
void add(int u,int v){
    cnt++;
    ed[cnt].to=v;
    ed[cnt].next=head[u];
    head[u]=cnt;
}
void dfs(int u,int fa){
    f[u][0]=fa;
    dep[u]=dep[fa]+1;
    for(int i=1;i<20;i++)f[u][i]=f[f[u][i-1]][i-1];
    for(int i=head[u];i;i=ed[i].next){
        int v=ed[i].to;
        if(v!=fa)dfs(v,u);
    }
}
int lca(int u,int v){
    if(dep[u]<dep[v])swap(u,v);
    for(int i=19;i>=0;i--)if(dep[u]-(1<<i)>=dep[v])u=f[u][i];
    if(u==v)return u;
    for(int i=19;i>=0;i--)if(f[u][i]!=f[v][i])u=f[u][i],v=f[v][i];
    return f[u][0];
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<n;i++){
        scanf("%d%d",&u,&v);
        add(u,v),add(v,u);
    }
    dfs(1,0);
    for(int i=1;i<=m;i++){
        scanf("%d%d%d",&u,&v,&w);
        int fa1=lca(u,v),fa2=lca(v,w),fa3=lca(w,u);
        if(fa1==fa2)printf("%d ",fa3);
        if(fa2==fa3)printf("%d ",fa1);
        if(fa3==fa1)printf("%d ",fa2);
        printf("%d
",dep[u]+dep[v]+dep[w]-dep[fa1]-dep[fa2]-dep[fa3]);
    }
}

结果RE两个点

忘改数组了(无语)

数组调大后就A了

原文地址:https://www.cnblogs.com/gzezzry/p/12190196.html