HDU 2586 How far away ?(LCA)

该题是一道比较基础的LCA(最近公共祖先),也就是快速求出树上任意两个点的最近公共祖先, 然后顺便维护边权值(每个结点到root的距离),就可以快速求出任意两个结点的距离了。

细节参见代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<stack>
using namespace std;
typedef long long ll;
const double eps = 1e-6;
const int INF = 1000000000;
const int maxn = 40000+5;
const int maxq = 200+5;
int T,n,u,v,k,m;
ll dist[maxn];
int f[maxn],answer[maxq], h[maxn], tt, q, root;
int _find(int x) {
    if(f[x] == -1) return x;
    return f[x] = _find(f[x]);
}
void bing(int u, int v) {
    int t1 = _find(u);
    int t2 = _find(v);
    if(t1 != t2) f[t1] = t2;
}
bool vis[maxn], flag[maxn];
int ancestor[maxn];
struct Edge {
    ll to, next, dist;
}edge[maxn*2];
int head[maxn], tot;
void addedge(int u, int v, int dist) {
    edge[tot].to = v;
    edge[tot].dist = dist;
    edge[tot].next = head[u];
    head[u] = tot++;
}
struct Query {
    int q, next, index;
}query[maxq*2];
void add_query(int u, int v, int index) {
    query[tt].q = v;
    query[tt].next = h[u];
    query[tt].index = index;
    h[u] = tt++;
    query[tt].q = u;
    query[tt].next = h[v];
    query[tt].index = index;
    h[v] = tt++;
}
void init() {
    tot = 0;
    memset(flag, false, sizeof(flag));
    memset(head, -1, sizeof(head));
    memset(dist, 0, sizeof(dist));
    tt = 0;
    memset(h, -1, sizeof(h));
    memset(vis, false, sizeof(vis));
    memset(f, -1, sizeof(f));
    memset(ancestor, 0, sizeof(ancestor));
}
void LCA(int u) {
    ancestor[u] = u;
    vis[u] = true;
    for(int i = head[u]; i != -1; i = edge[i].next) {
        int v = edge[i].to;
        if(vis[v]) continue;
        dist[v] = dist[u] + edge[i].dist;
        LCA(v);
        bing(u, v);
        ancestor[_find(u)] = u;
    }
    for(int i = h[u]; i != -1; i = query[i].next) {
        int v = query[i].q;
        if(vis[v]) {
            answer[query[i].index] = ancestor[_find(v)];
        }
    }
}
struct node{
    int u, v;
}a[maxq];
int main() {
    scanf("%d",&T);
    while(T--) {
        scanf("%d%d",&n,&m);
        init();
        for(int i=0;i<n-1;i++) {
            scanf("%d%d%d",&u,&v,&k);
            flag[v] = true;
            addedge(u, v, k);
            addedge(v, u, k);
        }
        for(int i=0;i<m;i++) {
            scanf("%d%d",&a[i].u,&a[i].v);
            add_query(a[i].u,a[i].v,i);
        }
        for(int i=1;i<=n;i++) {
            if(!flag[i]) {
                root = i; break;
            }
        }
        LCA(root);
        for(int i=0;i<m;i++) {
            int lca = answer[i], u = a[i].u , v = a[i].v;
            printf("%I64d\n",dist[u]+dist[v]-2*dist[lca]);
        }
    }
    return 0;
}


你可能感兴趣的:(数据结构,HDU,LCA,ACM-ICPC)