題意描述:
link
歡樂島上有個非常好玩的遊戲,叫做「緊急集合」。在島上分散有 \(n\) 個等待點,有 \(n−1\) 條道路連線著它們,每一條道路都連線某兩個等待點,且通過這些道路可以走遍所有的等待點,通過道路從乙個點到另乙個點要花費乙個遊戲幣。
參加遊戲的人三人一組,開始的時候,所有人員均任意分散在各個等待點上(每個點同時允許多個人等待),每個人均帶有足夠多的遊戲幣(用於支付使用道路的花費)、地圖(標明等待點之間道路連線的情況)以及對話機(用於和同組的成員聯絡)。當集合號吹響後,每組成員之間迅速聯絡,了解到自己組所有成員所在的等待點後,迅速在 \(n\) 個等待點中確定乙個集結點,組內所有成員將在該集合點集合,集合所用花費最少的組將是遊戲的贏家。
小可可和他的朋友邀請你一起參加這個遊戲,由你來選擇集合點,聰明的你能夠完成這個任務,幫助小可可贏得遊戲嗎?
最近公共祖先 水題。
一句話題意,讓你找到乙個點使得給出的三個點到這個點的距離盡可能的小。
手玩樣例可以發現,他只會是任意兩點之間的最近公共祖先,就直接列舉一下就行。
具體證明的話,就是說這樣會使重複的路徑盡可能的少。 (bushi).
好像還有一種 \(o(1)\) 的做法,主要是我沒看懂。
但樹剖常數小, \(5e5\) 的資料跑的沒有問題。
code:
#include#include#includeusing namespace std;
const int n = 5e5+10;
int n,m,u,v,x,y,z,ans,id,tot;
int dep[n],siz[n],son[n],top[n],head[n],fa[n];
struct node
e[n<<1];
inline int read()
while(ch >= '0' && ch <= '9')
return s * w;
}void add(int x,int y)
void get_tree(int x)
}void dfs(int x,int topp)
}int lca(int x,int y)
return dep[x] <= dep[y] ? x : y;
}int dis(int x,int y)
int main()
get_tree(1); dfs(1,1);
for(int i = 1; i <= m; i++)
lca = lca(x,z);
a = dis(x,lca), b = dis(y,lca), c = dis(z,lca);
if(ans > a+b+c)
lca = lca(y,z);
a = dis(x,lca), b = dis(y,lca), c = dis(z,lca);
if(ans > a+b+c)
printf("%d %d\n",id,ans);
} return 0;
}
P4281 AHOI2008 緊急集合 聚會
給定一棵樹,邊權為 1 多次詢問,給出三個點 a,b,c 求三個點的中點和到中點的總距離 定義中點為 x 滿足 dis a,x dis b,x dis c,x 最小 除錯日誌 jump 陣列開小,只開了 19 首先是樹上兩點距離 dis x,y dep x dep y 2 dep lca x,y 根...
AHOI2008 緊急集合 LCA
題目大意 給一棵樹,求三點之間最短距離,並求最短距離所在的點。題解 求出兩兩之間的lca,觀察可以發現,有兩個lca是相同的,且這個點一定在所有lca中深度最淺。畫乙個圖可以發現,集合點就是另乙個lca,因為這個點是這三個點互相路徑連線起來的公共點。至於距離,找個例子可以發現距離是dep a dep...
AHOI2008 緊急集合 聚會
歡樂島上有個非常好玩的遊戲,叫做 緊急集合 在島上分散有n個等待點,有n 1條道路連線著它們,每一條道路都連線某兩個等待點,且通過這些道路可以走遍所有的等待點,通過道路從乙個點到另乙個點要花費乙個遊戲幣。參加遊戲的人三人一組,開始的時候,所有人員均任意分散在各個等待點上 每個點同時允許多個人等待 每...