小b最近正在玩乙個尋寶遊戲,這個遊戲的地圖中有n個村莊和n-1條道路,並且任何兩個村莊之間有且僅有一條路徑可達。遊戲開始時,玩家可以任意選擇乙個村莊,瞬間轉移到這個村莊,然後可以任意在地圖的道路上行走,若走到某個村莊中有寶物,則視為找到該村莊內的寶物,直到找到所有寶物並返回到最初轉移到的村莊為止。小b希望評測一下這個遊戲的難度,因此他需要知道玩家找到所有寶物需要行走的最短路程。但是這個遊戲中寶物經常變化,有時某個村莊中會突然出現寶物,有時某個村莊內的寶物會突然消失,因此小b需要不斷地更新資料,但是小b太懶了,不願意自己計算,因此他向你求助。為了簡化問題,我們認為最開始時所有村莊內均沒有寶物
第一行,兩個整數n、m,其中m為寶物的變動次數。
接下來的n-1行,每行三個整數x、y、z,表示村莊x、y之間有一條長度為z的道路。
接下來的m行,每行乙個整數t,表示乙個寶物變動的操作。若該操作前村莊t內沒有寶物,則操作後村莊內有寶物;若該操作前村莊t內有寶物,則操作後村莊內沒有寶物。
m行,每行乙個整數,其中第i行的整數表示第i次操作之後玩家找到所有寶物需要行走的最短路程。若只有乙個村莊內有寶物,或者所有村莊內都沒有寶物,則輸出0。
4 5
1 2 30
2 3 50
2 4 6023
421
0
100220
220280
1<=n<=100000,1<=m<=100000,對於全部的資料,1<=z<=10^9
可以證明,從任意乙個有寶物的節點出發時,最後所需要的權都是相等的。所以我們直接動態維護關鍵點的虛樹,答案就是di
st(i
d[1]
,id[
2])+
dist
(id[
2],i
d[3]
)+··
·+di
st(i
d[k−
1],i
d[k]
)+di
st(i
d[k]
,id[
1]) dis
t(id
[1],
id[2
])+d
ist(
id[2
],id
[3])
+···
+dis
t(id
[k−1
],id
[k])
+dis
t(id
[k],
id[1
])
,k
為當前有寶藏的村莊數,id
陣列存放著按dfs序排序過後的有寶藏的村莊,那麼每一次加乙個點只要在原基礎上刪掉它按dfs序的前乙個點和後乙個點的距離、加上自己與那兩個點的距離就好了(注意邊界情況,即dfs序是最小的或者是最大的),刪除同理。
#include
const
int maxn = int(1e5) + 7, inf = 0x3f3f3f3f;
typedef
long
long ll;
std::set
st;
int n, m, cnt_edge, top, fa[maxn][17], id[maxn], dfn[maxn], deep[maxn], head_edge[maxn];
ll dist[maxn], ans, delta;
bool mark[maxn];
inline
void read(int &x, int ch = 0)
struct edge[maxn << 1];
inline
void insert(int u, int v, int w) ;
head_edge[u] = cnt_edge++;
}inline
void dfs(int u, int pre, int v = 0)
}inline
int lca(int x, int y)
inline ll dis(int x, int y)
int main()
}
BZOJ3991 尋寶遊戲 LCA 虛樹 SET
小b最近正在玩乙個尋寶遊戲,這個遊戲的地圖中有n個村莊和n 1條道路,並且任何兩個村莊之間有且僅有一條路徑可達。遊戲開始時,玩家可以任意選擇乙個村莊,瞬間轉移到這個村莊,然後可以任意在地圖的道路上行走,若走到某個村莊中有寶物,則視為找到該村莊內的寶物,直到找到所有寶物並返回到最初轉移到的村莊為止。小...
bzoj5329 圓方樹 虛樹 戰略遊戲
description 省選臨近,放飛自我的小q無心刷題,於是慫恿小c和他一起頹廢,玩起了一款戰略遊戲。這款戰略遊戲的地圖由n個城市以及m條連線這些城市的雙向道路構成,並且從任意乙個城市出發總能沿著道路走到 任意其他城市。現在小c已經占領了其中至少兩個城市,小q可以摧毀乙個小c沒占領的城市,同時摧毀...
血壓遊戲 科大訊飛杯G題 虛樹
一開始的時候,我往長鏈剖分上去寫,但是寫不好,最後寫成了當只有一條鏈的時候是 然後,開始想別的想法了,於是想 到了虛樹的做法。因為,我們可以發現,乙個點,向上影響的時候,只有同等深度的才會同時起作用,只要不是同等深度的時候,那麼他們的時間就會是錯開的,所以,我們可以對深度來進行處理。只有發生這種情況...