(由於本人太菜所以最近一直在補一些基礎算法……)
求樹的重心的基本思想就是從每個節點出發分別遍歷一遍樹,統計max_part,其中能夠使得max_part最小的就是樹的重心
另外:一棵有根樹至多有兩個重心,這個結論好像有些題可以用(比如BZOJ4337,不過那個數據太水只有50(什么暴力亂搞都能過去),但據高三的DZYO神仙說數據可以出到1e6)
大部分的解釋都在代碼里面(其實沒有什么好解釋的……我解釋了下各個變量的意思)
/*
樹的重心定義:對於一個樹中節點x,當我們刪去它時會將原來的樹分割成若干個不相連的部分,其中每個部分都是一顆子樹。
設max_part表示這些部分中最大的一棵子樹,若刪去節點x能夠使得max_part最小,則稱這個點為樹的重心
*/
void Dfs(int x){
/*
v[i]:遍歷的時候打標記
size[i]:刪去x后以i為根的子樹的大小
max_part:刪去x之后大小最大的子樹的大小
pos:搜索到現在使得max_part最小的節點
ans:搜到現在max_part的最小值
*/
v[x]=1; size[x]=1;
int max_part=0;
for(register int i=head[x];i;i=nxt[i]){
int y=ver[i];
if(v[y])continue;
Dfs(y);
size[x]+=size[y];
max_part=max(max_part,size[y]);
}
max_part=max(max_part,n-size[x]);
if(max_part<ans){
ans=max_part;
pos=x;
}
}
參考資料:李煜東《算法競賽進階指南》