• 倍增法-lca codevs 1036 商务旅行


    codevs 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

     1 #define N 60100
     2 #include<iostream>
     3 using namespace std;
     4 #include<cstdio>
     5 #include<cstring>
     6 #define C 20
     7 typedef long long ll;
     8 int ance[N>>1][C],dis[N>>1],n,a,b,m;
     9 ll sum=0;
    10 struct Edge{
    11     int v,last;
    12 }edge[N<<1];
    13 int deep[N>>1],head[N>>1],t=0;
    14 void add_edge(int u,int v)
    15 {
    16     ++t;
    17     edge[t].v=v;
    18     edge[t].last=head[u];
    19     head[u]=t;
    20 }
    21 void input()
    22 {
    23     scanf("%d",&n);
    24     for(int i=1;i<n;++i)
    25     {
    26         scanf("%d%d",&a,&b);
    27         add_edge(a,b);
    28         add_edge(b,a);/*注意树上建边必须是双向的*/
    29     }
    30 }
    31 void dfs(int k)
    32 {
    33     for(int l=head[k];l;l=edge[l].last)
    34     {
    35         if(!deep[edge[l].v])
    36         {
    37             dis[edge[l].v]=dis[k]+1;
    38             ance[edge[l].v][0]=k;
    39             deep[edge[l].v]=deep[k]+1;
    40             dfs(edge[l].v);
    41         }
    42     }
    43 }
    44 void chuli_ance()
    45 {
    46     for(int i=1;(1<<i)<=n;++i)
    47       for(int j=1;j<=n;++j)
    48       ance[j][i]=ance[ance[j][i-1]][i-1];
    49 }
    50 int lca(int a,int b)
    51 {
    52     int i,j;
    53     if(deep[a]<deep[b]) swap(a,b);
    54     for(i=0;(1<<i)<=deep[a];++i);
    55       i--;
    56     for(j=i;j>=0;--j)
    57       if(deep[a]-(1<<j)>=deep[b])
    58       a=ance[a][j];
    59     if(a==b) return a;
    60     for(j=i;j>=0;--j)
    61     {
    62         if(ance[a][j]!=-1&&ance[a][j]!=ance[b][j])
    63         {
    64             a=ance[a][j];
    65             b=ance[b][j];
    66         }
    67     }
    68     return ance[a][0];
    69 }
    70 int main()
    71 {
    72     input();
    73     deep[1]=1;
    74     dis[1]=0;
    75     memset(ance,-1,sizeof(ance));
    76     dfs(1);
    77     chuli_ance();
    78     scanf("%d",&m);
    79     scanf("%d",&a);
    80     int sta=a;
    81     for(int i=2;i<=m;++i)
    82     {
    83         scanf("%d",&b);
    84         int zuxian=lca(a,b);
    85         sum+=(dis[a]+dis[b]-2*dis[zuxian]);
    86         a=b;
    87     }
    88     sum+=dis[sta];
    89     cout<<sum<<endl;
    90     return 0;
    91 }
  • 相关阅读:
    团队选题报告
    第二次结对作业
    高级软件工程团队第一次作业
    第一次结队作业
    高级软件工程第二次作业
    高级软件工程第一次作业
    洛谷 题解 2165 [AHOI2009]飞行棋
    洛谷 题解 P1684 考验
    洛谷 题解 P4613 【[COCI2017-2018#5] Olivander】
    洛谷 题解 P5534 【【XR-3】等差数列】
  • 原文地址:https://www.cnblogs.com/c1299401227/p/5595029.html
Copyright © 2020-2023  润新知