• 商务旅行


    商务旅行

     

    时间限制: 1 s
    空间限制: 128000 KB 

     
    题目描述 Description

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

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

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

    输入描述 Input Description

    输入文件中的第一行有一个整数N,1<=n<=30 000,为城镇的数目。下面N-1行,每行由两个整数ab (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)的裸题,mark一下lca的写法。
    #include<iostream>
    #include<vector>
    #include<cmath>
    #include<cstring>
    #include<cstdio>
    #define N 100005
    using namespace std;
    
    struct edge{int v,w;};
    vector<edge>edges[N];
    int grand[N][25]={0},gw[N][25]={0};
    int depth[N],DEPTH,n;
    
    void addedge(int a,int b,int w)
    {
        edges[a].push_back((edge){b,w});
        edges[b].push_back((edge){a,w});
    }
    
    void dfs(int x)
    {
        for(int i=1;i<=DEPTH;i++)
        {
            grand[x][i]=grand[grand[x][i-1]][i-1];
            gw[x][i]=gw[x][i-1]+gw[grand[x][i-1]][i-1];
        }
    
        for(int i=0;i<edges[x].size();i++)
        {
            int to=edges[x][i].v;
            if(grand[x][0]==to)continue;
    
            depth[to]=depth[x]+1;
            grand[to][0]=x;
            gw[to][0]=edges[x][i].w;
            dfs(to);
        }
    }
    
    void init()
    {
        DEPTH=floor(log(n + 0.0) / log(2.0));
        depth[1]=1;
        memset(grand,0,sizeof(grand));
        memset(gw,0,sizeof(gw));
        dfs(1);
    }
    
    int lca(int a,int b)
    {
        if(depth[a]>depth[b])swap(a,b);
        int ans=0;
        for(int i=DEPTH;i>=0;i--)
        if(depth[a]<depth[b]&&depth[grand[b][i]]>=depth[a])
        ans+=gw[b][i],b=grand[b][i];
    
        for(int i=DEPTH;i>=0;i--)
        if(grand[a][i]!=grand[b][i])
        {
            ans+=gw[a][i];
            ans+=gw[b][i];
            a=grand[a][i];
            b=grand[b][i];
        }
    
        if(a!=b)
        {
            ans+=gw[a][0];
            ans+=gw[b][0];
        }
        return ans;
    }
    
    
    int main()
    {
        int a,b;
        scanf("%d",&n);
        for(int i=0;i<n-1;i++)
        {
            scanf("%d %d",&a,&b);
            addedge(a,b,1);
        }
    
        init();
    
        int ans=0;
        int m,last=1;
        scanf("%d",&m);
        while(m--)
        {
            scanf("%d",&a);
            ans+=lca(last,a);
            last=a;
        }
        printf("%d",ans);
    
        return 0;
    }
    View Code
     
  • 相关阅读:
    [转]JIRA 7.2.6与Confluence 6.0.3的安装与配置之MS SQL Server版
    Vue中computed和watch使用场景和方法
    vue插槽 slot 插槽之间的父子传参
    VUE 父子组件的传递 props、$ref 、 $emit、$parent、$children、$root
    div水平居中 垂直居中
    三次握手 四次挥手
    TCP/IP各层网络协议的通俗理解
    学习 cookie session 正向代理和反向代理的区别
    学习vuex心得体会
    登陆界面 跟后台对接口
  • 原文地址:https://www.cnblogs.com/tian-luo/p/9419938.html
Copyright © 2020-2023  润新知