樹的重心求法POJ3107

2021-07-09 13:01:46 字數 1891 閱讀 7735

題目的意思很明確,就是求所有樹的重心(再按字典序輸出)。

樹是很常見的資料結構,樹的重心在樹的分治中非常有用,所以對於大規模的樹快速求出重心省節時間是乙個oi選手需要考慮的問題。

那麼我們先介紹一下樹的重心。

樹的重心定義為:樹中的乙個點,刪掉該點,使剩下的樹所構成的森林中最大的子樹節點數最少。

樹的重心推論:

1.設樹上的乙個點s,樹上其餘所有點到s點的距離之和最小,那麼s就是重心。

2.樹的重心不唯一。

3.以樹的重心來做點分治,效率高如poj1741。

(見ioi2009中國國家集訓隊** 分治演算法在樹的路徑問題中的應用——漆子超)

那麼我們依靠定義來求樹的重心好了。

首先我們確定乙個根,進行一遍dfs,回溯的時候可以遞迴統計該點不同子樹所擁有的點的數量,然後再用(總節點數)減去(1)減去(子樹),就是其父親那邊的那棵樹的點的數量,區minn,最後求出即可。

***加速加速加速***

1.採用極速輸入(見我輸入輸出的**)。

2.採取陣列存邊。

加速效果:

我們看到,tle是僅採用極速輸入,用vector存邊的,效果非常差,2000ms的都沒a,不說了滿臉是淚啊。

然後呢,563ms的是僅採用陣列存邊,沒用極速輸入的。

(94ms那個不是這道題滾粗)— —

最後兩個優化都用上哈哈哈哈,157ms,該題總排名21(可惜沒進第一頁)

附**:

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

using

namespace

std;

typedef

long

long ll;

typedef

unsigned

long

long ull;

inline

int read()

int n;

int k;

int edge[100050];

int zhi[100050];

int zhong[100050];

int g=0;

int sum[100050];

int maxj[100050];

int minn=int_max;

void dfs(int d,int fa)

}maxj[d]=max(maxj[d],n-sum[d]-1);

minn=min(minn,maxj[d]);

sum[d]+=1;

sum[fa]+=sum[d];

maxj[fa]=max(sum[d],maxj[fa]);

return;

}int main()

dfs(1,0);

for(int i=1;i<=n;++i)

if(maxj[i]==minn)

cout

cout

/fclose(stdin);

//fclose(stdout);

return

0;}

poj3107(樹的重心)

求樹的重心。樹的重心是指去掉重心之後剩下的子樹的最大結點個數最少 樹形dp,dp i 表示以i為重心,剩下的子樹的最大結點個數,狀態轉移dp i max dp i siz j 注意用vector超時。如下 include include include include include include...

POJ 3107樹的重心

題意 找樹的重心。定義就是以重心為根的所有子樹裡面最大的最小。做法 瞎dfs一下就行了。記錄一下子樹。重點 這個題vector暴力存邊並不行。水了這麼多水題第一次被卡了。該來的總還是會來。所以用鏈式向前星來模擬鄰接表。比vector速度快的很多,也不難寫。include include includ...

POJ 3107樹的重心

題意 找樹的重心。定義就是以重心為根的所有子樹裡面最大的最小。做法 瞎dfs一下就行了。記錄一下子樹。重點 這個題vector暴力存邊並不行。水了這麼多水題第一次被卡了。該來的總還是會來。所以用鏈式向前星來模擬鄰接表。比vector速度快的很多,也不難寫。include include includ...