寻找树的中心(重心)
题目:
思路:
“剥洋葱”:每次剥掉一层叶子结点,直到最后剩余不多于2个节点,这些节点就是树的中心(重心)。
解释:
1、根据图论的知识可以知道,一颗树的中心(重心)至多有两个
2、叶子结点对于树的“半径”贡献最大,逐层剥离叶子结点可以逼近中心(重心)
代码:
#include<iostream>
#include<vector>
#include<queue>
#include<utility>
using namespace std;vector<int> findMinHeightTrees(int n, const vector<pair<int, int>>& edges)
{if (n == 1) return { 0 };//只有一个节点//1、构建邻接表,度数表vector<vector<int>> adj(n);vector<int> degree(n, 0);for (auto& e : edges){int u = e.first;int v = e.second;adj[u].push_back(v);adj[v].push_back(u);degree[u]++;degree[v]++;}//2、把所有叶子结点入队queue<int> q;for (int i = 0; i < n; i++)if (degree[i] == 1)q.push(i);//3、迭代“剥洋葱”,直至剩≤2个点int remaining = n;while (remaining > 2)//每次删完一圈叶子才会来到判断部分{int sz = q.size();remaining -= sz;for (int i = 0; i < sz; i++){int u = q.front();q.pop();//删除u,并更新邻居的度for (int v : adj[u])if (--degree[v] == 1)q.push(v);}}//4、队列中的节点即为最小高度树的根vector<int> roots;while (!q.empty()){roots.push_back(q.front());q.pop();}return roots;
}int main()
{int n;cin >> n;vector<pair<int, int>> edges(n - 1);for (int i = 0; i < n - 1; i++){cin >> edges[i].first >> edges[i].second;}vector<int> roots = findMinHeightTrees(n, edges);cout << "最小高度树的根节点有:";for (int x : roots)cout << x << " ";cout << endl;return 0;
}
运行结果: