樹的重心【poj1655】
阿新 • • 發佈:2018-11-09
定義
樹的重心也叫樹的質心。對於一棵樹n個節點的無根樹,找到一個點,使得把樹變成以該點為根的有根樹時,最大子樹的結點數最小。換句話說,刪除這個點後最大連通塊(一定是樹)的結點數最小。
數的重心求法其實非常簡單,用到了簡單的樹形dp的思想。
你只要進行一次dfs,一邊求以當前節點為根的子樹的節點數,一邊統計出子樹中最大的有max{f[j]}個節點(j為i的兒子)和i節點上方的子樹大小為n-f[i]個節點。這樣就可以找到重心了。
#include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; int n,cnt,T,a,b,mind,min0; int d[50035],head[50035],nxt[50035],to[50035]; void add(int x,int y) { cnt++;nxt[cnt]=head[x];to[cnt]=y;head[x]=cnt; } void dfs(int u,int fa) { d[u]=1; int max0=0; for (int i=head[u];i;i=nxt[i]) { int son=to[i]; if (son==fa) continue; dfs(son,u); d[u]=d[u]+d[son];//統計以u節點為根的子樹的節點個數 max0=max(max0,d[son]); } max0=max(max0,n-d[u]); if (min0>max0) { min0=max0; mind=u; } } int main() { scanf("%d",&T); while (T>0) { T--; min0=1e9+7; cnt=0; memset(head,0,sizeof(head)); scanf("%d",&n); for (int i=1;i<=n-1;i++) { scanf("%d%d",&a,&b); add(a,b); add(b,a); } dfs(1,0); printf("%d %d\n",mind,min0); } }