求樹的重心

2021-07-23 17:23:32 字數 2431 閱讀 7670

題目:

題意:給定一棵樹,求樹的重心的編號以及重心刪除後得到的最大子樹的節點個數size,如果size相同就選取編號最小的.

分析:首先要知道什麼是樹的重心,樹的重心定義為:找到乙個點,其所有的子樹中最大的子樹節點數最少,那麼這個點就是這棵

樹的重心,刪去重

心後,生成的多棵樹盡可能平衡.

實際上樹的重心在樹的點分治中有重要的作用, 可以避免n^2的極端複雜度(從退化鏈的一端出發),保證

nlogn的複雜度, 利用樹型dp可以很好地求樹的重心.

[cpp]view plain

copy

#include 

#include 

#include 

using

namespace

std;  

const

intn = 20005;  

const

intinf = 1<<30;  

inthead[n];  

intson[n];  

bool

vis[n];  

intcnt,n;  

intans,size;  

struct

edge  

;  edge edge[2*n];  

void

init()  

void

add(

intu,

intv)  

void

dfs(

intcur)  

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

if(tmp 

}  intmain()  

dfs(1);  

printf("%d %d\n"

,ans,size);  

}  return

0;  

}  

題目:

題意:給定一棵樹,求樹的所有重心,按照編號從小到大的順序輸出.

分析:本題與上題基本上一樣,只是求的量不同,既然我們在找樹的重心的時候用的樹型dp,而且是求的子樹中節點數的最大值,然後求所有最

大值的最小值,那麼就有可能存在多個重心,我們每更新到乙個最小值的時候就記錄其它的最小值也為這個最小值的重心,這樣下去就會找到所

有的重心.

[cpp]view plain

copy

#include 

#include 

#include 

#include 

using

namespace

std;  

const

intn = 50005;  

const

intinf = 1<<30;  

inthead[n];  

intson[n];  

bool

vis[n];  

intcnt,n;  

intnum,size;  

intans[n];  

struct

edge  

;  edge edge[2*n];  

void

init()  

void

add(

intu,

intv)  

void

dfs(

intcur)  

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

if(tmp 

else

if(tmp == size)  

}  intmain()  

dfs(1);  

sort(ans,ans+num);  

for(

inti=0;i

printf("%d "

,ans[i]);  

puts(""

);  

}  return

0;  

}  

如何求樹的重心

樹的重心 找到乙個點,其所有的子樹中最大的子樹節點數最少,那麼這個點就是這棵樹的重心,刪去重心後,生成的多棵樹盡可能平衡.打這個blog主要是為了等一下寫的點分治做鋪墊。例題t1 poj1655 題意 求一棵樹上的重心編號和去掉這個重心以後最大子樹的節點數。在dfs上做文章,每次對於乙個點,記錄下他...

求樹的重心 樹的直徑

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

bzoj2078 求樹的重心

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