[复习]LCA Tree

题目背景
SOURCE:NOIP2015-SHY

题目描述
给出一棵带有边权的树,问两点之间的距离。

输入格式
第一行两个整数 n 和 m ,分别表示点数和询问数。
接下来 n-1 行,每行三个整数 x,y,z,表示 x 与 y 通过一条权为 z 的边连接。
接下来 m 行,每行两个整数 x,y,代表一组询问。

输出格式
输出 m 行,每行一个整数,对应一组询问的答案。

样例数据
输入

3 3
1 2 1
1 3 2
1 2
1 3
2 3

输出

1
2
3

备注
【数据范围】
对 30% 的输入数据 :
1≤n,m≤1000
对 100% 的输入数据 :
1≤n,m≤100000;1≤z≤10000

分析: LCA模板

代码:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<algorithm>
#include<cctype>
#include<iomanip>
#include<queue>
#include<set>
using namespace std;

int getint()
{
    int sum=0,f=1;
    char ch;
    for(ch=getchar();!isdigit(ch)&&ch!='-';ch=getchar());
    if(ch=='-')
    {
        f=-1;
        ch=getchar();
    }
    for(;isdigit(ch);ch=getchar())
        sum=(sum<<3)+(sum<<1)+ch-48;
    return sum*f;
}

const int N=100010;
int n,m,tot;
int first[N],nxt[N*2],to[N*2],w[N*2];
int fa[N][25],dep[N],dis[N];
bool visit[N];

void addedge(int x,int y,int z)
{
    tot++;
    nxt[tot]=first[x];
    first[x]=tot;
    to[tot]=y;
    w[tot]=z;
    tot++;
    nxt[tot]=first[y];
    first[y]=tot;
    to[tot]=x;
    w[tot]=z;
}

void dfs(int u)
{
    for(int p=first[u];p;p=nxt[p])
    {
        int v=to[p];
        if(!visit[v])
        {
            visit[v]=true;
            dep[v]=dep[u]+1;
            dis[v]=dis[u]+w[p];
            fa[v][0]=u;
            for(int i=1;i<=20;++i)
                fa[v][i]=fa[fa[v][i-1]][i-1];
            dfs(v);
        }
    }
}

int lca(int x,int y)
{
    if(dep[x]<dep[y])
        swap(x,y);

    int len=dep[x]-dep[y];
    for(int i=20;i>=0;i--)
        if(len&(1<<i))
            x=fa[x][i];

    if(x==y)
        return x;
    for(int i=20;i>=0;i--)
        if(fa[x][i]!=fa[y][i])
        {
            x=fa[x][i];
            y=fa[y][i];
        }

    return fa[x][0];
}

int main()
{
    //freopen("LCA.in","r",stdin);
    //freopen("LCA.out","w",stdout);

    int x,y,z;
    n=getint(),m=getint();
    for(int i=1;i<n;++i)
    {
        x=getint(),y=getint(),z=getint();
        addedge(x,y,z);
    }

    dep[1]=0,dis[1]=0;
    visit[1]=true;
    dfs(1);

    while(m--)
    {
        x=getint(),y=getint();
        z=lca(x,y);
        cout<<dis[x]+dis[y]-2*dis[z]<<'\n';
    }
    return 0;
}

本题结。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值