树的重心及其性质
性质:
1.删除重心后所得的所有子树,节点数不超过原树的1/2,一棵树最多有两个重心;
2.树中所有节点到重心的距离之和最小,如果有两个重心,那么他们距离之和相等;
3.两个树通过一条边合并,新的重心在原树两个重心的路径上;
4.树删除或添加一个叶子节点,重心最多只移动一条边;
5.一棵树最多有两个重心,且相邻。
证明:https://www.cnblogs.com/suxxsfe/p/13543253.htm
附一个求树的重心的板子题:Codeforces Round #670 (Div. 2) C. Link Cut Centroids
#include<bits/stdc++.h> #define rep(i, n) for(int i=0;i!=n;++i) #define per(i, n) for(int i=n-1;i>=0;--i) #define Rep(i, sta, n) for(int i=sta;i!=n;++i) #define rep1(i, n) for(int i=1;i<=n;++i) #define per1(i, n) for(int i=n;i>=1;--i) #define Rep1(i, sta, n) for(int i=sta;i<=n;++i) #define L rt<<1 #define R rt<<1|1 #define inf (0x3f3f3f3f) #define llinf (1e18) #define ALL(A) A.begin(),A.end() #define SIZE(A) ((int)A.size()) #define MOD (1e9 + 7) #define PII pair<int,int> typedef long long i64; using namespace std; const int maxn = 1e5 + 32; vector<int> e[maxn]; int sz[maxn]; int rt,frt,n,x,p;//i节点连接的节点个数(除选定的根节点外) void dfs(int cur,int fa) { int mx = 0;//子节点最大的连接节点数 sz[cur] = 1;//因为连接了父节点 for(auto node: e[cur]) if(node != fa){ dfs(node,cur); sz[cur] += sz[node]; mx = max(mx,sz[node]); } if(sz[cur]*2>=n && mx*2 < n) // sz[cur]*2<=n 则每一个子树必 <=n/2,可知为重心,mx*2 < n确保为最深层的重心 rt = cur,frt = fa; } void solve() { int x,y; cin >> n; for(int i=1;i<=n;++i) e[i].resize(0); rep(i, n-1){ cin >> x >> y; e[x].push_back(y); e[y].push_back(x); } dfs(1, 0); if(rt == 1){ cout << "1 " << e[1][0] << endl; cout << "1 " << e[1][0] << endl; }else{ if(e[frt].size() == 1) p = rt,x = frt; else{ for(auto node: e[frt]) if(node != rt){ p = frt,x = node; break; } } cout << p << " " << x << endl;; cout << rt << " " << x << endl; } } int main() { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int t; cin >> t; while(t--) solve(); return 0; }
不怕万人阻挡,只怕自己投降。
posted on 2020-09-13 20:41 chengyulala 阅读(272) 评论(0) 编辑 收藏 举报