追捕遊戲 LCA

2021-08-08 09:21:36 字數 2041 閱讀 4948

問題描述

何老闆最近在玩一款追鋪遊戲,遊戲雖然簡單,何老闆仍舊樂此不疲。

遊戲地圖中有n座城市由n-1條雙向道路連線。任意兩座城市都可相互到達。一名罪犯從a城市出發沿最短路線逃往b城市。在罪犯出發的同時,何老闆控制一名警察從c城市出發去追捕那名罪犯。每條道路都有一定的長度(單位公尺)。罪犯和警察行走的速度相同,都是1秒鐘行走1公尺。

若罪犯到達b城市時還沒有被抓住,何老闆就輸掉了這局遊戲。何老闆總共玩了m局遊戲,每局遊戲開始前,何老闆想知道他是否能贏下這局遊戲,如果能,警察最少行走多少公尺才能抓到罪犯?

輸入格式

第一行,兩個整數n和m

接下來n-1行,每行三個整數x,y,z,表示城市x和y之間有一條長度為z的道路相連。

接下來m行,每行三個整數a,b,c。

輸出格式

m行,每行對應一局遊戲的結果。若能抓捕到罪犯。輸出乙個整數,表示警察最少需要行走的距離。若無法抓到罪犯,輸出-1。

樣例輸入

11 2

1 2 6

1 3 3

1 4 3

3 5 2

3 6 5

4 7 9

6 10 3

5 8 4

5 9 3

8 11 8

11 9 10

2 4 7

樣例輸出

10

9

樣例解釋

第1局在5號城市抓住罪犯。

第2局在4號城市抓住罪犯。

資料範圍

對於約40% 的資料:1<=n,m<=2000

對於100% 的資料:1<=n,m<=100000 1<=道路的長度<=10000

由於樹的性質,兩點之間有且僅有一條路徑。因此當c不在a、b的的路徑上時,c要到a、b的路徑上,只有乙個唯一的點d進行中轉(否則就會有環)。也就是說,警察的路徑也是唯一的。那麼只需要比較警察和小偷到達d點的時間即可。

通常的想法是,先找出d的位置,再計算dis(a,d)和dis(c,d)。然而這樣實現起來比較麻煩。事實上,容易得到以下關係:

dis(a,d)=dis(a,c)+dis(a,b)-2*dis(b,c)

dis(c,d)=dis(a,c)+dis(b,c)-2*dis(a,b)

快速查詢樹上兩點的距離,倍增即可。

#include

#define min(x,y) ((x#define maxm 200005

#define maxn 100005

int n,m,dis;

int en[maxm],las[maxn],nex[maxm],len[maxm],tot;

void add(int

x,int

y,int z)

int dep[maxn],fa[maxn][20],dis[maxn][20];

void dfs(int

x,int f,int z)

}int lca(int

x,int

y)int main()

dfs(1,0,0);

for(i=1;i<=m;i++)

}

小小總結一下:

樹上的一些問題,鑑於樹上兩點間有且僅有一條路徑,僅使用距離討論就可以簡單而方便的解決很多問題。

nkoj 4239 追捕遊戲

問題描述 何老闆最近在玩一款追鋪遊戲,遊戲雖然簡單,何老闆仍舊樂此不疲。遊戲地圖中有n座城市由n 1條雙向道路連線。任意兩座城市都可相互到達。一名罪犯從a城市出發沿最短路線逃往b城市。在罪犯出發的同時,何老闆控制一名警察從c城市出發去追捕那名罪犯。每條道路都有一定的長度 單位公尺 罪犯和警察行走的速...

GDOI2017 取石子遊戲 LCA

給出一棵樹,每個點都有乙個權值。對於每個節點,求去掉該節點的子樹後,剩下所有節點的權值mex 最小的沒有出現的非負整數。用權值線段樹合併亂搞顯然是可行的,但細節很多且需要卡常。我們考慮所有權值為 i 的節點對答案的影響。求所有節點的lca,那麼對於從lca向上到根的路徑上的節點,去掉子樹後的部分中一...

BZOJ3991 尋寶遊戲 LCA 虛樹 SET

小b最近正在玩乙個尋寶遊戲,這個遊戲的地圖中有n個村莊和n 1條道路,並且任何兩個村莊之間有且僅有一條路徑可達。遊戲開始時,玩家可以任意選擇乙個村莊,瞬間轉移到這個村莊,然後可以任意在地圖的道路上行走,若走到某個村莊中有寶物,則視為找到該村莊內的寶物,直到找到所有寶物並返回到最初轉移到的村莊為止。小...