BZOJ 1602 [Usaco2008 Oct]牧場行走

Description

N頭牛(2<=n<=1000)別人被標記爲1到n,在同樣被標記1到n的n塊土地上吃草,第i頭牛在第i塊牧場吃草。
這n塊土地被n-1條邊連接。 奶牛可以在邊上行走,第i條邊連接第Ai,Bi塊牧場,第i條邊的長度是Li(1<=Li<=10000)。
這些邊被安排成任意兩頭奶牛都可以通過這些邊到達的情況,所以說這是一棵樹。
這些奶牛是非常喜歡交際的,經常會去互相訪問,他們想讓你去幫助他們計算Q(1<=q<=1000)對奶牛之間的距離。

Input

*第一行:兩個被空格隔開的整數:N和Q

*第二行到第n行:第i+1行有兩個被空格隔開的整數:AI,BI,LI

*第n+1行到n+Q行:每一行有兩個空格隔開的整數:P1,P2,表示兩頭奶牛的編號。

Output

*第1行到第Q行:每行輸出一個數,表示那兩頭奶牛之間的距離。

Sample Input

4 2

2 1 2

4 3 2

1 4 3

1 2

3 2

Sample Output

2

7

HINT

Source

資格賽

lca

#include <iostream>
#include <cstdio>
using namespace std;
const int SZ = 1010;

struct Edge
{
    int f, t, d;
}es[SZ << 1];
int first[SZ << 1], nxt[SZ << 1], tot = 1;
int depth[SZ], fa[SZ], dis[SZ], jump[SZ][20];

void build(int f, int t, int d)
{
    es[++tot] = (Edge){f, t ,d};
    nxt[tot] = first[f];
    first[f] = tot;
}

void dfs(int u, int f)
{
    depth[u] = depth[f] + 1;
    fa[u] = f;
    jump[u][0] = f;
    for(int i = 1; i <= 16; i++)
        jump[u][i] = jump[jump[u][i - 1]][i - 1];   
    for(int i = first[u]; i; i = nxt[i])
    {
        int v = es[i].t;
        if(v == f) continue;
        dis[v] = dis[u] + es[i].d;
        dfs(v, u);
    }
}

int lca(int l, int r)
{
    if(depth[l] < depth[r]) swap(l, r);
    int t = depth[l] - depth[r];
    for(int i = 0; i <= 16; i++)
        if(t & (1 << i)) l = jump[l][i];
    for(int i = 16; i >= 0; i--)
        if(jump[l][i] != jump[r][i])
            l = jump[l][i], r = jump[r][i];
    if(l == r) return l;
    return jump[l][0];
}

int main()
{
    int n, q;
    scanf("%d%d", &n, &q);
    int f, t, d;
    for(int i = 1; i < n; i++)
    {
        scanf("%d%d%d", &f, &t, &d);
        build(f, t, d);
        build(t, f, d);
    }
    dfs(1, 0);
    for(int i = 1; i <= q; i++)
    {
        scanf("%d%d", &f, &t);
        int F = lca(f, t);
        int ans = dis[f] + dis[t] - 2 * dis[F];
        printf("%d\n", ans);
    }
    return 0;
}

發佈了62 篇原創文章 · 獲贊 4 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章