cogs 186. [USACO Oct08] 牧场旅行 树链剖分 LCA

186. [USACO Oct08] 牧场旅行

★★☆   输入文件:pwalk.in   输出文件:pwalk.out   逐字节对比
时间限制:1 s   内存限制:128 MB

n个被自然地编号为1..n奶牛(1<=n<=1000)正在同样被方便的编号为1..n的n个牧场中吃草。更加自然而方便的是,第i个奶牛就在第i个牧场中吃草。

其中的一些对牧场被总共的n-1条双向通道的一条连接。奶牛可以通过通道。第i条通道连接的两个牧场是A_i和B_i(1<=A_i<=N;1<=B_i<=N)其长度是L_i(1<=L_i<=10000)。

通道只会连接两个不同的牧场,所以这些通道使得整个牧场构成了一棵树。

奶牛们是好交际的希望能够经常的访问别的奶牛。急切地,它们希望你能通过告诉它们Q(1<=Q<=1000)对牧场的路径来帮助他们安排旅行。(这里将有Q个询问,p1,p2(1<=p1<=n;1<=p1<=n))

分数:200

问题名称:pwalk

输入格式:

  • 第1行:两个用空格隔开的整数:n和Q
  • 第2..n行:第i+1行包含三个用空格隔开的整数:A_i,B_i和L_i
  • 第n+1..N+Q行:每行包含两个用空格隔开的整数,代表两个不同的牧场,p1和p2

输入样例(file pwalk.in):

4 2
2 1 2
4 3 2
1 4 3
1 2
3 2

输出格式:

  • 第1..Q行:行i包含第i个询问的答案。

输出样例:

2
7

输出说明:

询问1:牧场1和牧场2的路径长度为2。 询问2:3->4->1->2;总长为7。

 

就是一个树链剖分求LCA

#include<bits/stdc++.h>
#define maxn 1005
using namespace std;
int N,Q;
vector<int> v[maxn],w[maxn];
int dis[maxn];
int size[maxn],dep[maxn],fa[maxn],son[maxn],pos[maxn],dfn[maxn];
int cnt,top[maxn];
void Dfs(int x)
{
    size[x]=1; 
    for(int i=0;i<v[x].size();i++)
    {
        int y=v[x][i];
        if(!size[y])
        {
            fa[y]=x;
            dep[y]=dep[x]+1;
               dis[y]=dis[x]+w[x][i];
            Dfs(y);
            size[x]+=size[y];
            if(size[y]>size[son[x]])
                son[x]=y;//更新重儿子 
        }
    }
}
void Dfs(int x,int Tp)
{
    top[x]=Tp;
    dfn[++cnt]=x;
    pos[x]=cnt;
    if(son[x])
    {
        Dfs(son[x],Tp);//先走重链 
    }
    for(int i=0;i<v[x].size();i++)
    {
        int to=v[x][i];
        if(!top[to])
        {
            Dfs(to,to);//轻链 
        }
    }
}
int LCA(int x,int y)
{
    while(top[x]!=top[y])
    {
        if(dep[top[x]]<dep[top[y]])
            swap(x,y);
        x=fa[top[x]];
    }
    if(dep[x]>dep[y])
        swap(x,y);
    return x;
}
int main()
{
//    freopen("pwalk.in","r",stdin);
//    freopen("pwalk.out","w",stdout);
    scanf("%d%d",&N,&Q);
    for(int i=2;i<=N;i++)
    {
        int x,y,z;
        scanf("%d%d%d",&x,&y,&z);
        v[x].push_back(y);
        w[x].push_back(z);
        v[y].push_back(x);
        w[y].push_back(z);
    }
    Dfs(1);Dfs(1,1);
    for(int i=1;i<=Q;i++){
        int x,y;
        scanf("%d%d",&x,&y);
        printf("%d\n",dis[x]+dis[y]-2*dis[LCA(x,y)]);
    }


    return 0;
}

 

posted @ 2019-08-13 11:18  DreamingBligo_Tido  阅读(134)  评论(0编辑  收藏  举报