【codevs 1036】商务旅行

来源:互联网 发布:centos 输入法切换 编辑:程序博客网 时间:2024/06/01 08:00

题目描述 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

注意:”下面n-1行……“

与小机房的树不同,这个题编号从1开始,所以dfs的过程和now都从1开始

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>using namespace std;const int maxn=30000+3;int first[maxn<<1],next[maxn<<1],tot=0;int deep[maxn],dist[maxn],fa[maxn][25];int s;int n,m;struct edge{    int f,t;}l[maxn<<1];void build(int f,int t){    l[++tot]=(edge){f,t};    next[tot]=first[f];    first[f]=tot;    return;}void init(int q,int h){    for(int i=first[h];i;i=next[i])    {        int at=l[i].t;        if(at==q) continue;        fa[at][0]=h;        deep[at]=deep[h]+1;        init(h,at);    }    return;}void make_lca(){    for(int j=1;j<=log2(n);j++)    for(int i=1;i<=n;i++)    fa[i][j]=fa[fa[i][j-1]][j-1];}int lca(int x,int y){    if(deep[x]<deep[y]) swap(x,y);    for(int i=log2(n);i>=0;i--)    {        if(deep[fa[x][i]]>=deep[y])        x=fa[x][i];    }    if(x==y) return y;    for(int i=log2(n);i>=0;i--)    {        if(fa[x][i]!=fa[y][i])        {            x=fa[x][i];             y=fa[y][i];        }    }    return fa[x][0];}int ask(int x,int y){    return deep[x] + deep[y] - (deep[lca(x,y)] << 1);}int main(){    int now=1;//    int ans=0;    int a,b;    scanf("%d",&n);    for(int i=1;i<n;i++)    {        scanf("%d%d",&a,&b);        build(a,b);        build(b,a);    }    init(1,1);//    make_lca();    scanf("%d",&m);    while(m--)    {        scanf("%d",&s);        ans+=ask(now,s);///        now=s;    }    cout<<ans<<endl;    return 0;}
原创粉丝点击