zoukankan      html  css  js  c++  java
  • 模板倍增LCA 求树上两点距离 hdu2586

    http://acm.hdu.edu.cn/showproblem.php?pid=2586

    课上给的ppt里的模板是错的,wa了一下午orz。最近总是被坑啊。。。

    题解:树上两点距离转化为到根的距离之和减去重复部分,相当于前缀和

    dis[x] + dis[y] - 2ll * dis[LCA(x, y)]
    #define _CRT_SECURE_NO_WARNINGS
    #include<cmath>
    #include<iostream>
    #include<stdio.h>
    #include<algorithm>
    #include<cstring>
    #include<stack>
    #include<vector>
    #include<string.h>
    using namespace std;
    #define rep(i,t,n)  for(int i =(t);i<=(n);++i)
    #define per(i,n,t)  for(int i =(n);i>=(t);--i)
    #define mmm(a,b) memset(a,b,sizeof(a))
    #define eps 1e-6
    #define pb push_back
    
    typedef long long ll;
    
    
    stack <int> dl;
    const int maxn=1e5+5;
    int f[maxn][16];
    int fa[maxn];
    ll dis[maxn];
    int dep[maxn];
    
    int n, m;
     vector<pair<int,ll> > E[maxn];
     void dfs(int rt,int p) {
         
         for (int i = 0; i < E[rt].size(); i++) {
             pair<int,int> v = E[rt][i];
             if (v.first == p)continue;
             fa[v.first] =rt ;
             dep[v.first] =dep[rt]+1 ;
             dis[v.first] = dis[rt] + v.second;
             dfs(v.first, rt);
         }
     }
    
    void Init_LCA() {
        for (int j = 0; (1 << j) <= n; ++j)
            for (int i = 1; i <= n; ++i)
                f[i][j] = -1;
        for (int i = 1; i <= n; ++i) f[i][0] = fa[i];
        for (int j = 1; (1 << j) <= n; ++j)
            for (int i = 1; i <= n; ++i)
                if (f[i][j - 1] != -1)
                    f[i][j] = f[f[i][j - 1]][j - 1];
    }
    int LCA(int x, int y) {
        if (dep[x] < dep[y]) swap(x, y);
        int i, lg;
        for (lg = 0; (1 << lg) <= dep[x]; ++lg);
        --lg;
        /// 使x往上走直到和y在同一水平线上;
        for (i = lg; i >= 0; --i)
            if (dep[x] - (1 << i) >= dep[y])
                x = f[x][i];
        if (x == y) return x;
        /// 此时x,y在同一水平线上,使x,y同时以相同的速度(2^j)往上走;
        for (i = lg; i >= 0; --i)
            if (f[x][i] != -1 && f[x][i] != f[y][i])
                x = f[x][i], y = f[y][i];
        return fa[x];
    }
    int main()
    {
        int t;
        cin >> t;
        while (t--) {
            
            cin >> n >> m;
            rep(i, 1, n)E[i].clear();
            //mmm(dis, 0); mmm(fa, 0); mmm(f, 0); mmm(dep, 0);
            rep(i, 1, n-1) {
                int x, y;
                ll z;
                scanf("%d%d%lld", &x, &y, &z);
                //f[x][0] = y;
                E[x].push_back(make_pair(y,z));
                E[y].push_back(make_pair(x,z));
            }
            dis[1] = 0;
            //fa[1] = 1;
            //dep[1] = 0;
            dfs(1, -1);
            Init_LCA();
            rep(i, 1, m) {
                int x, y;
                scanf("%d%d", &x, &y);
                printf("%lld
    ", dis[x] + dis[y] - 2ll * dis[LCA(x, y)]);
                
            }
            //cout << endl;
        }
        cin >> n;
        return 0;
    }/*
     2
    5 2
    1 2 10
    2 3 10
    3 4 10
    4  5 10
    1 5
    5 3
    
     
     */
    成功的路并不拥挤,因为大部分人都在颓(笑)
  • 相关阅读:
    人事面试测试篇25
    人事面试测试篇19
    人事面试测试篇24
    人事面试测试篇20
    人事面试测试篇18
    人事面试测试篇23
    人事面试测试篇21
    人事面试测试篇17
    明天……
    重装系统
  • 原文地址:https://www.cnblogs.com/SuuT/p/9362022.html
Copyright © 2011-2022 走看看