zoukankan      html  css  js  c++  java
  • hdu2586 How far away ?

    这里写图片描述

    这个题目只要建立一个树,然后查询任意2个点之间的距离,没有更新操作,所以可以用LCA来做。

    LCA就是寻找最近公共祖先,这有什么用呢?

    这是因为有一个性质,假设B和C的最近公共祖先是A,那么对于整个树的根节点D,

    都有:|BD|+|CD|-|AD|*2=|BC|

    也就是说,只要事先求出所有点到D的距离dist(dist的大小为n),

    然后对于输入的B和C,只需要求出最近公共祖先,即可利用上式得到答案。

    这里写图片描述

    借鉴:
    https://blog.csdn.net/nameofcsdn/article/details/52230548

    #include<iostream>
    #include<vector>
    using namespace std;
    
    struct node
    {
        int son;
        int distance;
    };
    
    int n;
    vector<node>v[40001];//存儿子标号
    int deep[40001];//每个点的深度
    int visitnum[80001];//遍历数是2*n-1
    int visitn[40001];//每个点的任意一个遍历数
    int vnum;
    int mins[80001][18];        //区间最小值
    int dist[40001];        //每个点到祖先的距离distance
    int fa[40001];
    
    void visit(int m, int d, int dis)       //遍历重编号、计算distance
    {
        vector<node>::iterator p;
        deep[m] = d;
        dist[m] = dis;
        for (p = v[m].begin(); p != v[m].end(); p++)
        {
            if (fa[(*p).son]>-1)continue;
            fa[(*p).son] = m;
            visitnum[vnum++] = m;   //存入访问的第vnum个点是哪个点
            visit((*p).son, d + 1, dis + (*p).distance);
        }
        visitn[m] = vnum;       //注意这2句的顺序
        visitnum[vnum++] = m;
    }
    
    void rmq()      //计算区间最小值
    {
        for (int i = 1; i <= 2 * n - 1; i++)mins[i][0] = visitnum[i];
        for (int j = 1; (1 << j) <= 2 * n - 1; j++)
        {
            for (int i = 1; i <= 2 * n - 1; i++)
            {
                mins[i][j] = mins[i][j - 1];
                int k = i + (1 << (j - 1));
                if (k <= 2 * n - 1 && deep[mins[i][j]] > deep[mins[k][j - 1]])
                    mins[i][j] = mins[k][j - 1];
            }
        }
    }
    
    int lca(int x, int y)   //求最近公共祖先
    {
        x = visitn[x], y = visitn[y];
        if (x > y)x ^= y ^= x ^= y;
        int j = 0;
        while ((1 << j) <= y - x + 1)j++;
        j--;
        int min = mins[y + 1 - (1 << j)][j];
        if (deep[min] > deep[mins[x][j]])min = mins[x][j];
        return min;
    }
    
    int main()
    {
        int t, m, x, y, l;
        cin >> t;
        while (t--)
        {
            cin >> n >> m;
            vnum = 1;
            for (int i = 1; i <= n; i++)
            {
                v[i].clear();   //初始化
                fa[i] = -1;
            }
            for (int i = 1; i < n; i++)
            {
                scanf("%d%d%d", &x, &y, &l);
                node nod1, nod2;
                nod1.distance = l, nod1.son = y;
                v[x].insert(v[x].end(), nod1);
                nod2.distance = l, nod2.son = x;
                v[y].insert(v[y].end(), nod2);
            }
            fa[1] = 1;
            visit(1, 1, 0);
            rmq();
            while (m--)
            {
                scanf("%d%d", &x, &y);
                printf("%d
    ", dist[x] + dist[y] - dist[lca(x, y)] * 2);
            }
        }
        return 0;
    }
  • 相关阅读:
    loadrunner—事务、TPS
    loadrunner—集合点rendezvous
    loadrunner—web_submit_data
    阿里云的docker仓库登陆打标签
    linux 下安装git服务器
    解决mvn clean后打包错:Cannot create resource output directory
    eclipse中创建的spring-boot项目在启动时指定加载那一个配置文件的设置
    docker命令
    springboot所有pom依赖
    pthon小游戏
  • 原文地址:https://www.cnblogs.com/bryce1010/p/9386918.html
Copyright © 2011-2022 走看看