zoukankan      html  css  js  c++  java
  • codevs 2370 小机房的树

    题目描述 Description

    小机房有棵焕狗种的树,树上有N个节点,节点标号为0到N-1,有两只虫子名叫飘狗和大吉狗,分居在两个不同的节点上。有一天,他们想爬到一个节点上去搞基,但是作为两只虫子,他们不想花费太多精力。已知从某个节点爬到其父亲节点要花费 c 的能量(从父亲节点爬到此节点也相同),他们想找出一条花费精力最短的路,以使得搞基的时候精力旺盛,他们找到你要你设计一个程序来找到这条路,要求你告诉他们最少需要花费多少精力

    输入描述 Input Description
    第一行一个n,接下来n-1行每一行有三个整数u,v, c 。表示节点 u 爬到节点 v 需要花费 c 的精力。
    第n+1行有一个整数m表示有m次询问。接下来m行每一行有两个整数 u ,v 表示两只虫子所在的节点
    输出描述 Output Description

    一共有m行,每一行一个整数,表示对于该次询问所得出的最短距离。

    样例输入 Sample Input

    3

    1 0 1

    2 0 1

    3

    1 0

    2 0

    1 2

    样例输出 Sample Output

    1

    1

    2

    数据范围及提示 Data Size & Hint

    1<=n<=50000, 1<=m<=75000, 0<=c<=1000

    裸的lca:

    #include<iostream>
    #include<cstdio>
    #define maxn 110000
    
    using namespace std;
    
    int head[maxn],deep[maxn],sum[maxn][22],f[maxn][22];
    int n,m,num,ans;
    struct node{
        int to,v,pre;
    }e[maxn];
    
    void Insert(int from,int to,int v)
    {
        e[++num].to=to;
        e[num].v=v;
        e[num].pre=head[from];
        head[from]=num;
    }
    
    void find_deep(int from,int now,int dep,int val)
    {
        deep[now]=dep;f[now][0]=from;sum[now][0]=val;
        for(int i=head[now];i;i=e[i].pre)
      {
            int v=e[i].to;
            if(v!=from)find_deep(now,v,dep+1,e[i].v);
        }
    }
    
    void find_father()
    {
        for(int i=1;i<=21;i++)
            for(int j=1;j<=n;j++)
                f[j][i]=f[f[j][i-1]][i-1];
        for(int i=1;i<=21;i++)
            for(int j=1;j<=n;j++)
                sum[j][i]=sum[f[j][i-1]][i-1]+sum[j][i-1];
    }
    
    int get(int a,int delta)
    {
        for(int i=0;i<=21;i++)
        {
            if(delta&(1<<i))ans+=sum[a][i],a=f[a][i];
        }
        return a;
    }
    
    int lca(int a,int b)
    {
        if(deep[a]<deep[b])swap(a,b);
        if(a==b)return 0;
        a=get(a,deep[a]-deep[b]);
        for(int i=21;i>=0;i--)
        {
            if(f[a][i]!=f[b][i])
    	{
                ans+=sum[a][i]+sum[b][i];
                a=f[a][i];b=f[b][i];
            }
        }
        if(a!=b)ans+=sum[a][0]+sum[b][0];
    }
    
    int main()
    {
        scanf("%d",&n);
        int x,y,z;
        for(int i=1;i<n;i++)
        {
            scanf("%d%d%d",&x,&y,&z);
            Insert(x+1,y+1,z);
            Insert(y+1,x+1,z);
        }
        find_deep(1,1,0,0);
        find_father();
        scanf("%d",&m);
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&x,&y);
            ans=0;lca(x+1,y+1);
            printf("%d
    ",ans);
        }
        return 0;
    }
    

      

      

  • 相关阅读:
    使用FolderBrowserDialog组件选择文件夹
    使用OpenFileDialog组件打开多个文
    使用OpenFileDialog组件打开对话框
    获取弹出对话框的相关返回值
    PAT 甲级 1139 First Contact (30 分)
    PAT 甲级 1139 First Contact (30 分)
    PAT 甲级 1138 Postorder Traversal (25 分)
    PAT 甲级 1138 Postorder Traversal (25 分)
    PAT 甲级 1137 Final Grading (25 分)
    PAT 甲级 1137 Final Grading (25 分)
  • 原文地址:https://www.cnblogs.com/lyqlyq/p/7198888.html
Copyright © 2011-2022 走看看