給定一棵樹,找出乙個點x,使得刪去x後,剩下的最大的子樹最小。
解法:從上圖知,刪去點i後,形成的森林為點i的若干子樹與i『上方』的部分。
s[i]表示以i為根的子樹的大小
s[i] = ∑s[j] + 1
s[i] = 1
考慮每個節點i,剩下的最大子樹的大小maxsize(i) = max,故計算出所有的maxsize(i)後取最優即可。
複雜度分析:
雖然每個點可能有很多兒子,但每條邊只會更新一次,而一共只有n-1條邊,故時間複雜度為o(n)。
#include#include#include#include#include#include#include#include#include#include#include#includeusing namespace std;
#define m 200005
int head[m],tot,mark[m],n;
struct node
nd[m];//雙向邊,要開大點
int ndnum,balance;
void add(int x,int y)
int dfs(int w)
mx=max(mx,n-sum);
if(mx
poj 1655 樹的重心
題意 給了乙個樹,去掉乙個結點後的子樹的節點數的最大值即平衡值,求最小的平衡值,如果平衡值相同,使節點號最小。思路 其實也就是求樹的重心。樹的重心是找到乙個點使其所有子樹中節點個數最大的子樹的結點數目最小,使生成的樹盡可能平衡。其實 求樹的重心,只需要隨便找個點作為根dfs,求每個節點的每個子樹的節...
poj 1655 樹的重心
因為建立的樹實際上主要是記錄點的無向圖g,dfs u,r 的r是用來防止遍歷子節點時dfs到父節點,還用到了記憶化,並且是在一次dfs時求答案,效率有點低,ac用時300ms include include include include include include include includ...
樹的重心 poj1655
樹的重心也叫樹的質心。對於一棵樹n個節點的無根樹,找到乙個點,使得把樹變成以該點為根的有根樹時,最大子樹的結點數最小。換句話說,刪除這個點後最大連通塊 一定是樹 的結點數最小。數的重心求法其實非常簡單,用到了簡單的樹形dp的思想。你只要進行一次dfs,一邊求以當前節點為根的子樹的節點數,一邊統計出子...