最近公共祖先(lca) hdu 2586

hdu 2586 How far away ?

题目大意:给定n-1条边构成一棵树,无向的;和m个询问,对于每一个询问按顺序回答。

结题思路:lca算法算出最近公共祖先,然后dis[u]+dis[v]-2*dis[father](father是u,v的最近公共祖先),小trick是在构造询问树的时候把权值设成询问对应的输入顺序

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <stack>
#include <vector>
using namespace std;
const int maxn=40000+10;
struct node
{
    int v,w,next;
}e[maxn<<1],q[maxn<<1];
int ehead[maxn],qhead[maxn],vis[maxn],fa[maxn],dis[maxn],ans[maxn];
int eT,qT;
int n,m;
void build(node *ed,int *head,int &T,int u,int v,int w)
{
    ed[T].v=v;
    ed[T].w=w;
    ed[T].next=head[u];
    head[u]=T++;
}
void init()
{
    memset(ans,0,sizeof(ans));
    memset(dis,0,sizeof(dis));
    memset(ehead,-1,sizeof(ehead));
    memset(qhead,-1,sizeof(qhead));
    memset(vis,0,sizeof(vis));
    for(int i=1;i<=n;i++)
        fa[i]=i;
    eT=qT=0;
    int u,v,w;
    for(int i=0;i<n-1;i++)
    {
        scanf("%d%d%d",&u,&v,&w);
        build(e,ehead,eT,u,v,w);
        build(e,ehead,eT,v,u,w);
    }
    for(int i=0;i<m;i++)
    {
        scanf("%d%d",&u,&v);
        build(q,qhead,qT,u,v,i);
        build(q,qhead,qT,v,u,i);
    }
}
int getf(int x)
{
    while(x!=fa[x])
    {
        fa[x]=getf(fa[x]);
        x=fa[x];
    }
    return x;
}
void dfs(int u)
{
    vis[u]=1;
    for(int i=ehead[u];~i;i=e[i].next)
    {
        int v=e[i].v;
        if(!vis[v])
        {
            dis[v]=dis[u]+e[i].w;
            dfs(v);
            fa[v]=u;
        }
    }
    for(int i=qhead[u];~i;i=q[i].next)
    {
        int v=q[i].v;
        if(vis[v])
        {
            ans[q[i].w]=dis[u]+dis[v]-2*dis[getf(v)];
        }
    }
}
int main()
{
    int kase;
    //freopen("in.txt","r",stdin);
    scanf("%d",&kase);
    while(kase--)
    {
        scanf("%d%d",&n,&m);
        init();
        dfs(1);
        for(int i=0;i<m;i++)
            printf("%d\n",ans[i]);
    }
    return 0;
}

 

你可能感兴趣的:(HDU)