传送门:点击打开链接
题意:找到树的重心,要求平衡点相同时编号越小越好
树重心是一个非常重要的东西,在树的分治中占有一席之地,能使树的分治的复杂度不会退化到O(n^2),是一种十分有效的手段
树的重心的定义:将某一点删除,一颗树会分成许多棵子树,。一个树T的重心就是,删除了重心后,得到的那些子树中的最大子树的点数是最小的
求法是利用树型dp的思路,很容易实现
#include<map> #include<set> #include<cmath> #include<stack> #include<queue> #include<cstdio> #include<cctype> #include<string> #include<vector> #include<cstring> #include<iostream> #include<algorithm> #include<functional> #define fuck printf("fuck") #define FIN freopen("input.txt","r",stdin) #define FOUT freopen("output.txt","w+",stdout) using namespace std; typedef long long LL; typedef pair<int, int> PII; const int MX = 20000 + 5; const int ME = 40000 + 5; const int INF = 0x3f3f3f3f; int Head[MX], Next[ME], rear; struct Edge { int u, v, cost; } E[ME]; void edge_init() { rear = 0; memset(Head, -1, sizeof(Head)); } void edge_add(int u, int v) { E[rear].u = u; E[rear].v = v; Next[rear] = Head[u]; Head[u] = rear++; } int T, n; int A[MX], ansn, ansid; int DFS(int u, int f) { A[u] = 1; int ret = 0; for(int i = Head[u]; ~i; i = Next[i]) { int v = E[i].v; if(v == f) continue; int nxt = DFS(v, u); ret = max(ret, nxt); A[u] += nxt; } ret = max(ret, n - A[u]); if(ret < ansn || (ret == ansn && u < ansid)) { ansn = ret; ansid = u; } return A[u]; } int main() {//FIN; scanf("%d", &T); while(T--) { edge_init(); ansn = INF, ansid = INF; scanf("%d", &n); for(int i = 1; i <= n - 1; i++) { int u, v; scanf("%d%d", &u, &v); edge_add(u, v); edge_add(v, u); } DFS(1, -1); printf("%d %d\n", ansid, ansn); } return 0; }