• 树上倍增 hdu 2586


    参考博客:

    代码:

    #include<stdio.h>
    #include<iostream>
    #include<algorithm>
    #include<math.h>
    #include<string.h>
    using namespace std;
    const int max_=8e4+1;
    int depth[max_];//节点深度
    int gw[max_][25];//第 i 点到2^j父亲的距离
    int fa[max_][25];//第 i 点的2^j父亲
    bool vis[max_];//标记数组
    int tot,N;
    struct Tree//
    {
         int to;
         int w;
         int next;
    }a[max_*2];
    int edge[max_*2];
    void add_edge(int x,int y,int w)//建树
    {
        a[tot].to=y;
        a[tot].w=w;
        a[tot].next=edge[x];
        edge[x]=tot++;
    }
    void dfs(int now,int deep)//dfs预处理
    {
        if(vis[now]==0)
        {
            vis[now]=1;
            depth[now]=deep;//记录节点的深度
        }
        for(int i=edge[now];i!=-1;i=a[i].next)
        {
            int to=a[i].to;
            if(vis[to])
            continue;
            int w=a[i].w;
            gw[to][0]=w;//to到父亲的距离
            fa[to][0]=now;//to的父亲节点
            dfs(to,deep+1);
        }
    }
    void LCA_init(int n)//预处理
    {
        for(int i=1;i<=n;i++)
            for(int j=1;j<=N;j++)
        {
            fa[i][j]=fa[fa[i][j-1]][j-1];
            gw[i][j]=gw[fa[i][j-1]][j-1]+gw[i][j-1];
        }
    }
    int LCA_Q(int u,int v)
    {
        int ans=0;//距离
        if(depth[u]<depth[v])
            swap(u,v);//保证大减小
        int k;
            k=depth[u]-depth[v];
        for(int i=0;(1<<i)<=k;i++)
        {
            if((1<<i)&k)
               ans+=gw[u][i],u=fa[u][i];
        }
            if(u==v)
                return ans;//找到了就退出
            for(int i=N;i>=0;i--)
            {
                if(fa[u][i]!=fa[v][i])
                {
                    ans+=gw[u][i],
                    ans+=gw[v][i];
                    u=fa[u][i],
                    v=fa[v][i];
                }
            }
            return ans+=gw[v][0]+gw[u][0];
    }
    void init(int n)//初始化
    {
        memset(vis,0,sizeof(vis));
        tot=0;
        N=(int)(log(n+0.0)/log(2));
        memset(edge,-1,sizeof(edge));
    }
    int main()
    {
        int t;
        cin>>t;
        while(t--)
        {
            int n,m;
            scanf("%d %d",&n,&m);
            init(n);
            for(int i=0;i<n-1;i++)
            {
                int u,v,w;
                scanf("%d %d %d",&u,&v,&w);
                add_edge(u,v,w);
                add_edge(v,u,w);
            }
            dfs(1,0);
            LCA_init(n);
            while(m--)
            {
                int u,v;
                scanf("%d %d",&u,&v);
                int L=LCA_Q(u,v);
                printf("%d
    ",L);
            }
           /* for(int i=1;i<=n;i++)
                printf("%d ",fa[i][2]);*/
        }
    }
    /*
    13 2
    1 2 1
    1 3 1
    1 4 1
    2 5 1
    3 6 1
    6 10 1
    6 11 1
    10 13 1
    4 7 1
    4 8 1
    4 9 1
    8 12 1
    */
      /*  for(int x=max0;x>=0;x--)     //注意!此处循环必须是从大到小!因为我们应该越提越“精确”,
            if(fa[u][x]!=fa[v][x])   //如果从小到大的话就有可能无法提到正确位置,自己可以多想一下
            {
                u=fa[u][x];
                v=fa[v][x];
            }
        return fa[u][0];    //此时u、v的第一个父亲就是LCA。*/
  • 相关阅读:
    Redhat as 版本下启用 Telnet 和 FTP 服务
    Eclipse中设置编码的方式
    rhel3上安装Oracle(来自Oracle网站)
    home/end的快捷键~
    Red Hat Linux 9中文本模式与图形模式的切换
    Highcharts:非常漂亮的图表API
    Linux裸设备总结(ZT)
    Red Hat Linux操作系统下从文本模式切换到图形模式的方法
    pear
    Java中的asList
  • 原文地址:https://www.cnblogs.com/linhaitai/p/9814033.html
Copyright © 2020-2023  润新知