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

数据范围及提示 Data Size & Hint

 

LCA 

求上一个地点last到下一地点a的LCA x

距离等于

deep[last]+deep[a]-2*deep[x]。

但是我不明白的是TLE 开大数组就过了 

屠龙宝刀点击就送

#include <algorithm>
#include <cstring>
#include <cstdio>
#define Max 30000

using namespace std;

struct Edge
{
    int next,to;
}edge[Max*3];
struct point
{
    int fa,size,chain,deep;
}p[Max+1000];
int kk,head[Max*3],cnt,n,m,a;
void qr(int &x)
{
    x=0;int f=1;
    char ch=getchar();
    while(ch>'9'||ch<'0')
    {
        if(ch=='-') f=-1;
         ch=getchar();
    }
    while(ch>='0'&&ch<='9')
    {
        x=x*10+(int)ch-48;
        ch=getchar();
    }
    x*=f;
}
void add(int u,int v)    
{
    cnt++;
    edge[cnt].next=head[u];
    edge[cnt].to=v;
    head[u]=cnt;
}
void dfs1(int now,int fa)
{
    int pos=kk++;
    p[now].fa=fa;
    p[now].deep=p[p[now].fa].deep+1;
    for(int i=head[now];i;i=edge[i].next)
    {
        if(edge[i].to==fa) continue;
        dfs1(edge[i].to,now);
    }
    p[now].size=kk-pos;
}
void dfs2(int now,int chain)
{
    int pos=0;
    p[now].chain=chain;
    for(int i=head[now];i;i=edge[i].next)
    {
        if(p[edge[i].to].chain) continue;
        if(p[pos].size<p[edge[i].to].size)
        pos=edge[i].to;
    }
    if(pos) dfs2(pos,chain);
    else return;
    for(int i=head[now];i;i=edge[i].next)
    {
        if(edge[i].to==p[now].fa||edge[i].to==pos) continue;
        dfs2(edge[i].to,edge[i].to);
    }
}
int lca(int x,int y)
{
    while(p[x].chain!=p[y].chain)
    {
        if(p[p[x].chain].deep<p[p[y].chain].deep)
        swap(x,y);
        x=p[p[x].chain].fa;
    }
    return p[x].deep<p[y].deep?x:y;
}
int main()
{
    qr(n);
    int k=n-1;
    for(int a,b;k--;)
    {
        qr(a);qr(b);
        add(a,b);
        add(b,a);
    }
    dfs1(1,0);
    kk=0;dfs2(1,1);
    int v;
    qr(m);    qr(v);
    m-=1;
    int ans=0;
    for(int x,last=v;m--;)
    {
        qr(v);
        x=lca(v,last);
        ans+=p[v].deep+p[last].deep-(2*p[x].deep);
        last=v;
    }
    printf("%d",ans);
    return 0;
}

 

posted @ 2017-03-16 20:09  杀猪状元  阅读(168)  评论(0编辑  收藏  举报