zoukankan      html  css  js  c++  java
  • 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;
    }
    心若向阳,无谓悲伤
    折花枝,恨花枝,准拟花开人共卮,开时人去时。 怕相思,已相思,轮到相思没处辞,眉间露一丝。
  • 相关阅读:
    boost::asio在VS2008下的编译错误
    Java集合框架——接口
    ACM POJ 3981 字符串替换(简单题)
    ACM HDU 1042 N!(高精度计算阶乘)
    OneTwoThree (Uva)
    ACM POJ 3979 分数加减法(水题)
    ACM HDU 4004 The Frog's Games(2011ACM大连赛区第四题)
    Hexadecimal View (2011ACM亚洲大连赛区现场赛D题)
    ACM HDU 4002 Find the maximum(2011年大连赛区网络赛第二题)
    ACM HDU 4001 To Miss Our Children Time (2011ACM大连赛区网络赛)
  • 原文地址:https://www.cnblogs.com/L-Memory/p/6344821.html
Copyright © 2011-2022 走看看