如何求樹的重心

2021-07-16 23:38:25 字數 1701 閱讀 3124

樹的重心:找到乙個點,其所有的子樹中最大的子樹節點數最少,那麼這個點就是這棵樹的重心,刪去重心後,生成的多棵樹盡可能平衡.

打這個blog主要是為了等一下寫的點分治做鋪墊。

例題t1:poj1655

題意:求一棵樹上的重心編號和去掉這個重心以後最大子樹的節點數。

在dfs上做文章,每次對於乙個點,記錄下他子樹中的最大節點,然後更新一下編號和子樹節點大小就可以了。

#include 

#include

#include

using

namespace

std;

const

int n = 20005;

const

int inf = 1

<<30;

int head[n];

int son[n];

bool vis[n];

int cnt,n;

int ans,size;

struct edge

; edge edge[2*n];

void init()

void add(int u,int v)

void dfs(int cur)

} tmp = max(tmp,n-son[cur]-1);

if(tmp < size || tmp == size && cur < ans)

} int main()

dfs(1);

printf("%d %d\n",ans,size);

} return

0;

}

例題2:poj3107

其實這題跟上題差不多,只不過這次是要求所有的重心的編號,那麼跟之前一樣,只不過記得把每次更新的答案記錄下來最後排序之後輸出就行了。

#include 

#include

#include

#include

using

namespace

std;

const

int n = 50005;

const

int inf = 1

<<30;

int head[n];

int son[n];

bool vis[n];

int cnt,n;

int num,size;

int ans[n];

struct edge

; edge edge[2*n];

void init()

void add(int u,int v)

void dfs(int cur)

} tmp = max(tmp,n-son[cur]-1);

if(tmp < size)

else

if(tmp == size)

} int main()

dfs(1);

sort(ans,ans+num);

for(int i=0;iprintf("%d ",ans[i]);

puts("");

} return

0;

}

求樹的重心

題目 題意 給定一棵樹,求樹的重心的編號以及重心刪除後得到的最大子樹的節點個數size,如果size相同就選取編號最小的.分析 首先要知道什麼是樹的重心,樹的重心定義為 找到乙個點,其所有的子樹中最大的子樹節點數最少,那麼這個點就是這棵 樹的重心,刪去重 心後,生成的多棵樹盡可能平衡.實際上樹的重心...

求樹的重心 樹的直徑

樹的重心 樹的重心是指樹上一點,去掉後最大子樹可以取得最小值的點。求解方法 樹的重心定義 去掉該點後最大子樹大小不超過n 2。重心為1 樹的直徑指樹上最遠兩點的距離 方法 先隨便找個點,找到離他最遠的點,再在那個最遠的點上找一次最遠的點,這兩個點之間的距離就是直徑。include define ma...

bzoj2078 求樹的重心

時間限制 1 sec 記憶體限制 128 mb 樹的重心定義為樹的某個節點,當去掉該節點後,樹的各個連通分量中,節點數最多的連通分量其節點數達到最小值。樹可能存在多個重心。如下圖,當去掉點1後,樹將分成兩個連通塊 2,4,5 3,6,7 則最大的連通塊包含節點個數為3。若去掉點2,則樹將分成3個部分...