求樹的重心
阿新 • • 發佈:2018-08-11
font struct target printf 樹的點分治 size 復雜度 編號 鏈接
給定一棵樹,求樹的重心的編號以及重心刪除後得到的最大子樹的節點個數size,如果size相同就選取編號最小的.
首先要知道什麽是樹的重心,樹的重心定義為:找到一個點,其所有的子樹中最大的子樹節點數最少,那麽這個點就是這棵樹的重心,刪去重
心後,生成的多棵樹盡可能平衡. 實際上樹的重心在樹的點分治中有重要的作用, 可以避免N^2的極端復雜度(從退化鏈的一端出發)
算法就是跑一遍dfs,找到最優解。
鏈接
代碼:
#include <iostream> #include <string.h> #include <stdio.h> usingnamespace 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 { int to; int next; }; Edge edge[2*N]; void Init() { cnt = 0; size = INF; memset(vis,0,sizeof(vis)); memset(head,-1,sizeof(head)); } void add(int u,int v) { edge[cnt].to = v; edge[cnt].next = head[u]; head[u] = cnt++; } void dfs(int cur) { vis[cur] = 1; son[cur] = 0; int tmp = 0; for(int i=head[cur]; ~i; i=edge[i].next) { int u = edge[i].to; cout<<u<<endl;if(!vis[u]) { dfs(u); son[cur] += son[u] + 1; tmp = max(tmp,son[u] + 1); } } tmp = max(tmp,n-son[cur]-1); if(tmp < size || tmp == size && cur < ans) { ans = cur; size = tmp; } } int main() { int T; scanf("%d",&T); while(T--) { Init(); scanf("%d",&n); for(int i=1; i<=n-1; i++) { int u,v; scanf("%d%d",&u,&v); add(u,v); add(v,u); } dfs(1); printf("%d %d\n",ans,size); } return 0; }
求樹的重心