POJ 1655 Balancing Act (树形DP求树的重心)

时间:2023-03-08 15:51:28

题意:

求一棵树中以某个点为重心最小的子树集, 就是去掉这个点, 图中节点最多的联通块节点最少。

分析:

想知道这个点是不是最优的点, 只要比较它子树的数量和除去这部分其他的数量(它的父节点那部分树), 最后循环一遍找最优即可。

#include<stdio.h>
#include<vector>
#include<algorithm>
#include<string.h>
#include<iostream>
using namespace std; const int maxn = + ;
const int inf = 1e9 + ;
int Max[maxn];//记录以该节点为重心,子树节点的最大值
int Num[maxn];//记录包括该节点不回溯到父亲节点有多少个子节点
vector<int> G[maxn];
int N;
void init() {
for(int i = ; i < maxn; i ++) {
G[i].clear();
}
}
void dpMax(int u, int pre) { Num[u] = , Max[u] = ; for(int i = ; i < G[u].size(); i++) {
int v = G[u][i];
if(v == pre)
continue;
dpMax(v, u);
Max[u] = max(Max[u], Num[v]);
Num[u] += Num[v];
}
Max[u] = max(Max[u], N - Num[u]);//比较一下自己子树和父亲子树的最大值 }
int main() {
int T;
cin >> T;
while(T--) {
init();
cin >> N;
for(int i = ; i < N - ; i++) {
int u, v;
cin >> u >> v;
G[u].push_back(v);
G[v].push_back(u);
}
// Max[0] = inf;
dpMax(, -);
int ansNum = inf, ansInd = ;
for(int i = ; i <= N; i++){
if(ansNum > Max[i]){
ansNum = Max[i];
ansInd = i;
}
}
cout << ansInd << " " << ansNum << "\n";
}
return ;
}