hdu2586 lca模板题

树上询问两节点距离

#include<bits/stdc++.h>
#define fi first
#define se second
#define log2(a) log(n)/log(2)
#define show(a) cout<<a<<endl;
#define show2(a,b) cout<<a<<" "<<b<<endl;
#define show3(a,b,c) cout<<a<<" "<<b<<" "<<c<<endl;
using namespace std;

typedef long long ll;
typedef pair<int, int> P;
typedef pair<P, int> LP;
const ll inf = 1e17 + 10;
const int N = 40010 + 10;
const ll mod = 998244353;
const int base=131;
const double pi=acos(-1);
map<string, int>ml;


map<int,int> mp;
map<int,int> vi;
priority_queue<P> q;
priority_queue<P> tq;
string s;


//int b[N], vis[N], dep[N],num[5005], t, n, m, x, y, k,a[N];
//ll ex, ey, cnt, ans, sum, flag;

int fa[N][30], deep[N],n,m,t,x,y,w;
int dis[N];

struct node
{
    int to, w;
};

vector<node> graph[N];


void dfs(int v)//dfs求每一子节点到根节点的距离存放到dis数组
{
    deep[v]=deep[fa[v][0]]+1;
    for(int i=0;fa[v][i];++i){fa[v][i+1]=fa[fa[v][i]][i];}//进行树上倍增fa[v][i]代表v向上2^i层的父节点
    for(auto i:graph[v])
    {
        if(deep[i.to] ){continue;}
        dis[i.to]=dis[v]+i.w;
        fa[i.to][0]=v;
        dfs(i.to);
    }
    return ;
}

int lca(int a,int b)
{
    if(deep[a]<deep[b])swap(a,b);
    int i;
    for(i=20;i>=0;--i)//将a跳转到与b相同deep的父节点
    {
        if(deep[fa[a][i]]>=deep[b]){a=fa[a][i];}
    }
    if(a==b)return a;
    for(i=20;i>=0;--i)//求a,b的公共节点
    {
        if(fa[a][i]!=fa[b][i]){a=fa[a][i];b=fa[b][i];}
    }
    return fa[a][0];
}


int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cin>>m;
    while(m--)
    {

        cin>>n>>t;
        memset(deep,0,sizeof deep);
        memset(dis,0,sizeof dis);
        memset(graph,0,sizeof graph);
        memset(fa,0,sizeof fa);
        for(int i=1;i<n;i++)
        {
            int w;
            cin>>x>>y>>w;
            graph[x].push_back(node{y,w});
            graph[y].push_back(node{x,w});
        }
        dfs(1);
        for(int i=1;i<=t;i++)
        {
            cin>>x>>y;
            cout<<dis[x]+dis[y]-2*dis[lca(x,y)]<<endl;
        }
    }


}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值