樹的重心:找到乙個點,其所有的子樹中最大的子樹節點數最少,那麼這個點就是這棵樹的重心,刪去重心後,生成的多棵樹盡可能平衡.
打這個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個部分...