题目来源 leetcode310
给定一个无根树,要求输出某些结点,这些结点在成为根之后,树的高度最小。
计算这个树的每个结点的度,删除所有度为一的结点生成一个新树,再删除所有度为一的结点,如此循环。最后剩下的一个或两个结点就是所求结点,算法复杂度为O(V+E),因为这和用BFS进行拓扑排序的过程是相同的。这个算法为什么是正确的呢?首先对于一棵树,若结点数大于2,则其度数为一结点绝对不是所求结点,因为度数为一结点的邻结点作为根的话树的高度会比较小,所求树根一定不在度数为一的结点中。这样,度数为一的结点一定是以所求树根为树根的树的叶子,删除所有叶子之后,以其他任何一个结点作为树根的树的高度比原树小一,所以删除叶子结点之后最佳树根不变。因此,可以不断地删除度数为一的结点,直到结点数目小于等于2为止。
vector<int> BFS(vector<vector<int> >& list, vector<int>& degree)
{
queue<int> q;
vector<int> ans;
if (list.size() == 1)
{
ans.push_back(0);
}
int n=list.size();
for (int i = 0; i < degree.size(); i++)
{
if (degree[i] == 1)
q.push(i);
}
while (!q.empty())
{
int x = q.size();
for (int k = 0; k < x; k++)
{
degree[q.front()]--;
for (int i = 0; i < list[q.front()].size(); i++)
{
degree[list[q.front()][i]]--;
if (degree[list[q.front()][i]] == 1)
{
q.push(list[q.front()][i]);
}
}
if (n <= 2)
{
ans.push_back(q.front());
}
q.pop();
}
n -= x;
}
return ans;
}
vector<int> findMinHeightTrees(int n, vector<pair<int, int>>& edges) {
vector<vector<int> > list(n);
vector<int> degree(n);
for (int i = 0; i < edges.size(); i++)
{
list[edges[i].first].push_back(edges[i].second);
list[edges[i].second].push_back(edges[i].first);
}
for (int i = 0; i < n; i++)
{
degree[i] = list[i].size();
}
vector<int> ans = BFS(list, degree);
return ans;
}