• 小机房的树


    【题目描述】

    小机房有一棵树,树上有n(1 <= n <= 50000)个节点,标号为0~n-1,有两只虫子分居在两个不同的节点上,他们想爬到一个节点上去,已知从某个节点爬到其父亲节点要花费c(0 <= c <= 1000)精力(从父亲节点爬到此节点也相同),询问它们最少花费多少精力才能到达目标节点。

    【输入描述】

    第一行输入一个整数n;

    接下来n-1行,每行输入三个整数u、v、c,表示从节点u爬到节点v花费c精力;

    第n+1行输入一个整数m(1 <= m <= 75000),表示询问次数;

    接下来m行,每行输入两个整数u、v,表示两只虫子所在的节点标号。

    【输出描述】

    输出m行,每行包含一个整数,表示对于该次询问所得出的答案。

    【样例输入】

    3

    1 0 1

    2 0 1

    3

    1 0

    2 0

    1 2

    【样例输出】

    1

    1

    2

    源代码:
    
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    struct Node
    {
        int S,To,Next;
    }Edge[150001];
    int n,m,Num(0),i[50001],f[50001][22],Head[50001],Deep[50001];
    void Add(int t1,int t2,int t) //边表。
    {
        Edge[++Num].To=t2;
        Edge[Num].S=t;
        Edge[Num].Next=Head[t1];
        Head[t1]=Num;
    }
    void DFS(int T,int S) //DFS预处理深度Deep[]和直系父亲f[][0],T表示当前节点,S表示当前深度。
    {
        Deep[T]=S;
        for (int a=Head[T];a;a=Edge[a].Next)
        {
            int t=Edge[a].To;
            if (!Deep[t]&&t) //防止回溯向上,并特判0。
            {
                f[t][0]=T;
                i[t]=i[T]+Edge[a].S; //i[]表示从根节点到当前节点的距离。
                DFS(t,S+1);
            }
        }
    }
    void Get_Father() //类似于ST表,记录父系关系,f[i][j]表示i节点的2^j层父亲的节点编号。
    {
        for (int b=1;b<=21;b++) //一般不会超过此值。
          for (int a=0;a<n;a++) //节点编号为0~(n-1)。
            f[a][b]=f[f[a][b-1]][b-1]; //2^j层父亲一定就是2^(j-1)层父亲的2^(j-1)层父亲。
    }
    int Get_Same(int T,int S) //深度调节。
    {
        for (int a=0;a<=21;a++)
          if ((1<<a)&S)
            T=f[T][a];
        return T;
    }
    int LCA(int t1,int t2)
    {
        if (Deep[t1]<Deep[t2]) //预处理。
          swap(t1,t2);
        t1=Get_Same(t1,Deep[t1]-Deep[t2]); //使其上升到相同深度。
        for (int a=21;a>=0;a--) //逆序才能由粗到细。
          if (f[t1][a]!=f[t2][a])
          {
            t1=f[t1][a];
            t2=f[t2][a];
          }
        if (t1==t2) //根节点。
          return t1;
        return f[t1][0];
    }
    int main() //此题节点编号为0~(n-1)。
    {
        scanf("%d",&n);
        for (int a=1;a<n;a++)
        {
            int t,t1,t2;
            scanf("%d%d%d",&t1,&t2,&t);
            Add(t1,t2,t);
            Add(t2,t1,t);
        }
        i[0]=0;
        DFS(0,0); //默认根节点为0。
        Get_Father();
        scanf("%d",&m);
        for (int a=0;a<m;a++) //第一次打倍增LCA,QAQ。
        {
            int t1,t2;
            scanf("%d%d",&t1,&t2);
            int Ans=LCA(t1,t2);
            if (Ans==t1) //是否在一条链上。
              printf("%d
    ",i[t2]-i[t1]);
            else
              printf("%d
    ",i[t1]+i[t2]-(i[Ans]<<1));
        }
        return 0;
    }
  • 相关阅读:
    PowerDesigner如何导出建表sql脚本(转)
    excel插入行时提示不能将对象移到工作表外,怎么解决!!
    Axure知识点
    移动互联网学习的点
    什么是大数据?
    [Android开源项目] GitHub开源项目总结 (转)
    程序员自我提高的几点建议 很实诚(转)
    程序员必须进行的10项投资(转)
    安卓版本的问题
    Android APK反编译详解(转)
  • 原文地址:https://www.cnblogs.com/Ackermann/p/5701397.html
Copyright © 2020-2023  润新知