zoukankan      html  css  js  c++  java
  • 商务旅行(codevs 1036)

    题目描述 Description

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

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

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

    输入描述 Input Description

    输入文件中的第一行有一个整数N,1<=n<=30 000,为城镇的数目。下面N-1行,每行由两个整数a 和b (1<=a, b<=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

    /*
      倍增 LCA 
    */
    #include<cstdio>
    #include<iostream>
    #include<vector>
    #define M 30010
    #define S 20
    using namespace std;
    int deep[M],fa[M][S+5],n,m;
    vector<int> grap[M];
    void dfs(int now,int from,int c)
    {
        fa[now][0]=from;
        deep[now]=c;
        for(int i=0;i<grap[now].size();i++)
          if(from!=grap[now][i])
            dfs(grap[now][i],now,c+1);
    }
    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];
    }
    int get_same(int a,int t)
    {
        for(int i=0;i<=S;i++)
          if(t&(1<<i)) a=fa[a][i];
        return a;
    }
    int LCA(int a,int b)
    {
        if(deep[a]<deep[b])swap(a,b);
        a=get_same(a,deep[a]-deep[b]);
        if(a==b)return a;
        for(int i=S;i>=0;i--)
          if(fa[a][i]!=fa[b][i])
            {
                a=fa[a][i];
                b=fa[b][i];
            }
        return fa[a][0];
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<n;i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            grap[x].push_back(y);
            grap[y].push_back(x);
        }
        dfs(1,1,0);
        get_fa();
        int p1,p2,ans=0;
        scanf("%d%d",&m,&p1);
        for(int i=1;i<m;i++)
        {
            scanf("%d",&p2);
            int zu=LCA(p1,p2);
            ans+=(deep[p1]+deep[p2]-2*deep[zu]);
            p1=p2;
        }
        printf("%d",ans);
        return 0;
    }
    View Code
  • 相关阅读:
    Word中如何删除目录页的页码
    在java程序代码中打开文件
    Web程序报错:Error instantiating servlet
    将日期类型数据写入到数据库中
    《将博客搬至CSDN》
    软件测试工程师常见的面试题
    我对需求文档的理解
    简单的学生管理系统,实现增删改查
    如何求两个数的最大公约数
    【转载】LoadRunner监控window系统各项指标详解
  • 原文地址:https://www.cnblogs.com/harden/p/5653853.html
Copyright © 2011-2022 走看看