树的重心及其性质
性質:
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;
}
總結
- 上一篇: SAP Commerce的extensi
- 下一篇: SAP Commerce(原Hybris