• codevs1026商务旅行


    1036 商务旅行

     

     时间限制: 1 s
     空间限制: 128000 KB
     题目等级 : 钻石 Diamond
     
     
     
    题目描述 Description

    某首都城市的商人要经常到各城镇去做生意,他们按自己的路线去做,目的是为了更好的节约时间。

    假设有N个城镇,首都编号为1,商人从首都出发,其他各城镇之间都有道路连接,任意两个城镇之间如果有直连道路,在他们之间行驶需要花费单位时间。该国公路网络发达,从首都出发能到达任意一个城镇,并且公路网络不会存在环。

    你的任务是帮助该商人计算一下他的最短旅行时间。

    输入描述 Input Description

    输入文件中的第一行有一个整数N,1<=n<=30 000,为城镇的数目。下面N-1行,每行由两个整数a 和b (1<=ab<=n; a<>b)组成,表示城镇a和城镇b有公路连接。在第N+1行为一个整数M,下面的M行,每行有该商人需要顺次经过的各城镇编号。

    输出描述 Output Description

        在输出文件中输出该商人旅行的最短时间。

    样例输入 Sample Input
    5
    1 2
    1 5
    3 5
    4 5
    4
    1
    3
    2
    5
    样例输出 Sample Output

    7

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define maxn 30010
    #define S 16
    
    using namespace std;
    int n,m,num,head[maxn],fa[maxn][S+5],deep[maxn],p1,p2,ans;
    struct node{
        int from;
        int to;
        int next;
    }e[maxn*2];
    
    void add(int from,int to)
    {
        e[++num].from=from;
        e[num].to=to;
        e[num].next=head[from];
        head[from]=num;
    }
    
    void swap(int &a,int &b)
    {
        int t=a;a=b;b=t;
    }
    
    void init()
    {
        scanf("%d",&n);
        int x,y;
        for(int i=1;i<=n-1;i++)
          {
              scanf("%d%d",&x,&y);
              add(x,y);add(y,x);
          }
    }
    void get_fa()
    {
        for(int j=1;j<=S;j++)
          for(int i=1;i<=n;i++)
            fa[i][j]=fa[fa[i][j-1]][j-1];
    }
    
    void Dfs(int now,int from,int c)//每个点所在层数 
    {
        fa[now][0]=from;
        deep[now]=c;
        for(int i=head[now];i;i=e[i].next)
         {
             int v=e[i].to;
             if(v!=from)
               Dfs(v,now,c+1);
         }
    }
    
    int get_same(int a,int t)
    {
        for(int i=0;i<16;i++)
         if(t&(1<<i)) a=fa[a][i];
        return a;
        /*
          if(deep[f[a][i]]>deep[t])
            a=f[a][i];
        */
    int LCA(int a,int b)
    {
        if(deep[a]<deep[b]) swap(a,b);//保证a深度大 
        a=get_same(a,deep[a]-deep[b]);//得到a向上deep[a]-deep[b]层是谁 即a的与b同层的祖先是谁
        if(a==b) return a;//如果汇聚到一个点 就不用往上了怎么不理我了?不赞同吗? 
        for(int i=S;i>=0;i--)//从最大值开始循环 一开始 fa[a][i]  fa[b][i]一定是相等的
                           //因为此时位于他们lca之上 然后往下 这里可以覆盖每一层 
        {
            if(fa[a][i]!=fa[b][i])
                    {
                        a=fa[a][i];
                        b=fa[b][i];
                  }
        }
            return fa[a][0];
    }
    
    int main()
    {
        init();
        Dfs(1,1,0);
        get_fa();
        scanf("%d%d",&m,&p1);
        for(int i=1;i<=m-1;i++)
          {
              scanf("%d",&p2);
              int anc=LCA(p1,p2);
              ans+=deep[p1]+deep[p2]-2*deep[anc];
              p1=p2;
          }
        printf("%d
    ",ans);
        return 0;
    }
    心若向阳,无谓悲伤
    折花枝,恨花枝,准拟花开人共卮,开时人去时。 怕相思,已相思,轮到相思没处辞,眉间露一丝。
  • 相关阅读:
    浅谈python web三大框架
    Mysql异常
    格式化时间转换
    MySql存储日期为long型,判断时间大小
    Linux下部署项目
    excel
    Tomcate的启动问题
    计算时间差
    地图系的转换
    关于获取本机真实IP
  • 原文地址:https://www.cnblogs.com/L-Memory/p/6344821.html
Copyright © 2020-2023  润新知