HDU 2586

题意:

一道很裸的LCA题

以一个点建树,两点间最短的距离可以转化为求两近公共祖先,最短距离,depth[x]-depth[l]+depth[y]-depth[l]

在dfs求得每个点到顶点距离

#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
const int maxn=4e4+5;
const int maxbit=15;
struct edge
{
    int to;
    int val;
};
int father[maxn][maxbit];
int depth[maxn];
int dis[maxn];vector<edge>G[maxn];
int lg[maxn];
void dfs(int nowp,int fa)
{
    depth[nowp]=depth[fa]+1;
    father[nowp][0]=fa;
    for(int j=1;j<=lg[depth[nowp]];j++)
     father[nowp][j]=father[father[nowp][j-1]][j-1];
     for(int i=0;i<G[nowp].size();i++)
     {
         edge e=G[nowp][i];
         if(e.to!=fa)
         {
             dis[e.to]=dis[nowp]+e.val;//算距离 
             dfs(e.to,nowp);
        }
     }
}
int lca(int u,int v)
{
    if(depth[u]<depth[v])
    swap(u,v);
    while(depth[u]!=depth[v])
    u=father[u][lg[depth[u]-depth[v]]];
    if(u==v)return u;
    for(int j=lg[depth[u]];j>=0;j--)
    {
        if(father[u][j]!=father[v][j])
        {
            u=father[u][j];
            v=father[v][j];
        }
    }
    return father[u][0];
}
int main()
{
    lg[0]=-1;
    for(int i=1;i<maxn;i++)
    lg[i]=lg[i>>1]+1;
    int t;
    scanf("%d",&t);
    while(t--)
    {
        memset(father,0,sizeof father);
        memset(depth,0,sizeof depth);
        memset(dis,0,sizeof dis);
        int n,m;
        scanf("%d%d",&n,&m);
        int x,y,k;
        for(int i=1;i<n;i++)
        {
            scanf("%d%d%d",&x,&y,&k);
            G[x].push_back({y,k});
            G[y].push_back({x,k});
        }
        dfs(1,0);
        while(m--)
        {
            scanf("%d%d",&x,&y);
            int l=lca(x,y);
            printf("%d
",(dis[x]-dis[l])+(dis[y]-dis[l]));
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/flyljz/p/11687493.html