Format
The graph contains n
nodes which are labeled from 0
to n - 1
. You will be given the number n
and a list of undirected edges
(each edge is a pair of labels).
You can assume that no duplicate edges will appear in edges
. Since all edges are undirected, [0, 1]
is the same as [1, 0]
and thus will not appear together in edges
.
Example 1:
Given n = 4
, edges = [[1, 0], [1, 2], [1, 3]]
0 | 1 / \ 2 3
return [1]
Example 2:
Given n = 6
, edges = [[0, 3], [1, 3], [2, 3], [4, 3], [5, 4]]
0 1 2 \ | / 3 | 4 | 5
return [3, 4]
Hint:
Show Hint- How many MHTs can a graph have at most?
Note:
(1) According to the definition of tree on Wikipedia: “a tree is an undirected graph in which any two vertices are connected by exactly one path. In other words, any connected graph without simple cycles is a tree.”
(2) The height of a rooted tree is the number of edges on the longest downward path between the root and a leaf.
题目的大意是给定一棵树,一棵树的根节点是可以随意指定的,题目要求我们找出使得树的高度最小的根节点的集合。
解这道题目的方法是每次都去掉树中的所有叶子节点,这样逐层地去除叶子节点,那么最后一层的结点就是使得树的高度最小的根节点。
对于上述结论,我在这里做一个简单的证明,如果我们按照去除结点的顺序给所有结点分层,最后去除的结点在第一层,最早去除的结点在最后一层,所以度数为1的点一定在最后一层中,也就是说所以叶子结点都在最后一层,假设以非第一层的结点作为根节点使得树的高度比当前的高度小,我们不妨假设这个结点在根节点偏左侧的分支中,如果树的高度比原来的小,也就是说根节点右侧的分支的高度是小于原来的高度的,也就是说右侧分支的叶结点不在最后一层,这与上述结论矛盾。
具体的算法是根据边集计算每个顶点的度数,并存在向量d中,并且用二维向量g建立一个邻接表,对于每个结点,把与它邻接的所有点都保存在向量中,然后就开始逐层地删除结点,每次都判断每个结点的度数是否为1或0(度数为0却还没有被删除的情况只有在只剩一个顶点的情况下出现),如果是就删除改点,并把同一层的所有结点都放在向量result中,而为了标记改点已经被删除,要把它的度数设为-1,在把同一层的叶子结点都删除以后,再逐个点地删除它们对应的边,按照这样的方法循环操作,循环的结束条件是所有点都已经被删除,而为了简化判断操作,我用delnum记录当前已经被删的结点数,也就是说只要delnum的值等于n就可以停止循环了。而最后的答案就是最后一层的结点,这些结点都保存在向量result中,
计算这个算法的时间复杂度比较困难,在while循环中的第一个for循环的复杂度是节点数乘以树的高度,也就是O(V*logV),第二个for循环是每条边都遍历两次,也就是O(E),由于这个图是一棵树,所以时间复杂度应该是O(V*logV)。
以下为源程序:
(n);
int delnum=0;
for(int i=0;i<edges.size();i++)
{
g[edges[i].first].push_back(edges[i].second);
g[edges[i].second].push_back(edges[i].first);
d[edges[i].first]++;
d[edges[i].second]++;
}
vector<int> result;
while(delnum<n)
{
result.clear();
for(int i=0;i<n;i++)
if(d[i]==1||d[i]==0)
{
d[i]=-1;
delnum++;
result.push_back(i);
}
for(int i=0;i<result.size();i++)
{
for(int j=0;j<g[result[i]].size();j++)
if(d[g[result[i]][j]]!=-1)
d[g[result[i]][j]]--;
}
}
return result;
}
};