• HDU2586 How far away?(倍增LCA算法求带边权树上最短路)


    题意:

    勇气小镇是一个有着n个房屋的小镇,为什么把它叫做勇气小镇呢,这个故事就要从勇气小镇成立的那天说起了,
    修建小镇的时候,为了让小镇有特色,镇长特地只修了n-1条路,并且规定说,所有在勇气小镇的村民,每一次出门必须规划好路线,
    路线必须满足在到达终点之前绝对不走回头路。每个人都要这样,不然那个人就不配在小镇生活下去,因为他没有这个勇气。
    事实上,这并不能算一项挑战,因为n-1条路已经连通了每户人家,不回头地从起点到终点,只是一个时间上的问题。
    由于小镇上的福利特别好,所以小懒入住了这个小镇,他规划了m次的行程,每次从L房屋到R房屋,他想问你他每次从L房屋到R房屋最少能走多少路。

    题解:

    倍增LCA求树上最短路,这颗树是带边权的树,所以需要加一个数组。

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    const int maxn=1e5+10;
    int head[maxn];
    int tol;
    int N,M;
    struct node {
        int u;
        int v;
        int w;
        int next;
    }edge[maxn];
    void addedge (int u,int v,int w) {
        edge[tol].u=u;
        edge[tol].v=v;
        edge[tol].w=w;
        edge[tol].next=head[u];
        head[u]=tol++;
    }
    
    //lca
    int father[20][maxn];
    int h[maxn];
    int d[maxn];
    void dfs (int x) {
        for (int i=head[x];i!=-1;i=edge[i].next) {
            int v=edge[i].v;
            if (v==father[0][x]) continue;
            father[0][v]=x;
            h[v]=h[x]+1;
            d[v]=d[x]+edge[i].w;
            dfs(v);
        }
    } 
    int lca (int x,int y) {
        if (h[x]<h[y]) swap(x,y);
        for (int i=17;i>=0;i--) 
            if (h[x]-h[y]>>i) x=father[i][x];
        if (x==y) return x;
        for (int i=17;i>=0;i--) {
            if (father[i][x]!=father[i][y]) {
                x=father[i][x];
                y=father[i][y];
            }
        }
        return father[0][x];
    }
    int getDis (int x,int y) {
        return d[x]+d[y]-d[lca(x,y)]*2;
    }
    int main () {
        int T;
        scanf("%d",&T);
        while (T--) {
            scanf("%d%d",&N,&M);
            memset(head,-1,sizeof(head));
            memset(father,0,sizeof(father));
            memset(h,0,sizeof(h));
            memset(d,0,sizeof(d));
            tol=0;
            for (int i=0;i<N-1;i++) {
                int u,v,w;
                scanf("%d%d%d",&u,&v,&w);
                addedge(u,v,w);
                addedge(v,u,w);
            }
            dfs(1);
            for (int i=1;i<=17;i++) 
                for (int j=1;j<=N;j++)
                    father[i][j]=father[i-1][father[i-1][j]];
            for (int i=0;i<M;i++) {
                int u,v;
                scanf("%d%d",&u,&v);
                printf("%d
    ",getDis(u,v));
            }
        }
        return 0;
    }
  • 相关阅读:
    static变量的生命周期
    关于C++的new是否会对内存初始化的问题
    行列式的本质是什么?
    C++本质:类的赋值运算符=的重载,以及深拷贝和浅拷贝
    C++拷贝(复制)构造函数详解
    随机生成指定长度字符字符串(C语言实现)
    【npm】npm install的报错
    【HTTP】http请求url参数包含+号,被解析为空格
    【ngx-ueditor】百度编辑器按下Shift键不触发contentChange事件
    【Angular】No component factory found for ×××.
  • 原文地址:https://www.cnblogs.com/zhanglichen/p/12526609.html
Copyright © 2020-2023  润新知