给出最小高度的树的根
给定一个具有树特征的无向图。可以选择任何节点作为根,任务是只找到那些最小化树高度的节点。
例子:
在下图中,所有节点都被一一设为根,我们可以看到当 3 和 4 为根时,树的高度最小(2)所以 {3, 4} 是我们的答案。
我们可以通过首先考虑一维解决方案来解决这个问题,即如果给定最长的图,那么如果总节点数为奇数,则将高度最小化的节点将是中间节点,如果总数为中间二节点节点数是偶数。这个解决方案可以通过以下方法实现——从路径的两端开始两个指针,每次移动一步,直到指针相遇或离开一步,最后指针将位于那些将高度最小化的节点,因为我们有均匀划分节点,使高度最小。
同样的方法也可以应用于一般树。从所有叶子节点开始指针,每次向内移动一步,移动时不断组合重叠的指针,最后只有一个指针会留在某个顶点上,或者两个指针会保持在一个距离上。这些节点代表顶点的根,它将最小化树的高度。
因此,如上所述,根据树结构,我们可以只有一个根或最多两个根以获得最小高度。对于实现,我们不会使用实际的指针,而是遵循类似 BFS 的方法,在开始时将所有叶节点推入队列,然后将它们从树中删除,下一个新叶节点被推入队列,此过程保持一直持续到我们的树中只有 1 或 2 个节点,它们代表结果。
C++
// C++ program to find root which gives minimum height to tree
#include
using namespace std;
// This class represents a undirected graph using adjacency list
// representation
class Graph
{
public:
int V; // No. of vertices
// Pointer to an array containing adjacency lists
list *adj;
// Vector which stores degree of all vertices
vector degree;
Graph(int V); // Constructor
void addEdge(int v, int w); // To add an edge
// function to get roots which give minimum height
vector rootForMinimumHeight();
};
// Constructor of graph, initializes adjacency list and
// degree vector
Graph::Graph(int V)
{
this->V = V;
adj = new list[V];
for (int i = 0; i < V; i++)
degree.push_back(0);
}
// addEdge method adds vertex to adjacency list and increases
// degree by 1
void Graph::addEdge(int v, int w)
{
adj[v].push_back(w); // Add w to v’s list
adj[w].push_back(v); // Add v to w’s list
degree[v]++; // increment degree of v by 1
degree[w]++; // increment degree of w by 1
}
// Method to return roots which gives minimum height to tree
vector Graph::rootForMinimumHeight()
{
queue q;
// first enqueue all leaf nodes in queue
for (int i = 0; i < V; i++)
if (degree[i] == 1)
q.push(i);
// loop until total vertex remains less than 2
while (V > 2)
{
int popEle = q.size();
V -= popEle; // popEle number of vertices will be popped
for (int i = 0; i < popEle; i++)
{
int t = q.front();
q.pop();
// for each neighbour, decrease its degree and
// if it become leaf, insert into queue
for (auto j = adj[t].begin(); j != adj[t].end(); j++)
{
degree[*j]--;
if (degree[*j] == 1)
q.push(*j);
}
}
}
// copying the result from queue to result vector
vector res;
while (!q.empty())
{
res.push_back(q.front());
q.pop();
}
return res;
}
// Driver code
int main()
{
Graph g(6);
g.addEdge(0, 3);
g.addEdge(1, 3);
g.addEdge(2, 3);
g.addEdge(4, 3);
g.addEdge(5, 4);
// Function Call
vector res = g.rootForMinimumHeight();
for (int i = 0; i < res.size(); i++)
cout << res[i] << " ";
cout << endl;
}
Python3
# Python program to find root which gives minimum
# height to tree
# This class represents a undirected graph using
# adjacency list representation
class Graph:
# Constructor of graph, initialize adjacency list
# and degree vector
def __init__(self, V, addEdge, rootForMinimumHeight):
self.V = V
self.adj = dict((i, []) for i in range(V))
self.degree = list()
for i in range(V):
self.degree.append(0)
# The below lines allows us define methods outside
# of class definition
# Check http://bit.ly/2e5HfrW for better explanation
Graph.addEdge = addEdge
Graph.rootForMinimumHeight = rootForMinimumHeight
# addEdge method adds vertex to adjacency list and
# increases degree by 1
def addEdge(self, v, w):
self.adj[v].append(w) # Adds w to v's list
self.adj[w].append(v) # Adds v to w's list
self.degree[v] += 1 # increment degree of v by 1
self.degree[w] += 1 # increment degree of w by 1
# Method to return roots which gives minimum height to tree
def rootForMinimumHeight(self):
from queue import Queue
q = Queue()
# First enqueue all leaf nodes in queue
for i in range(self.V):
if self.degree[i] == 1:
q.put(i)
# loop until total vertex remains less than 2
while(self.V > 2):
p = q.qsize()
self.V -= p
for i in range(p):
t = q.get()
# for each neighbour, decrease its degree and
# if it become leaf, insert into queue
for j in self.adj[t]:
self.degree[j] -= 1
if self.degree[j] == 1:
q.put(j)
# Copying the result from queue to result vector
res = list()
while(q.qsize() > 0):
res.append(q.get())
return res
# Driver code
g = Graph(6, addEdge, rootForMinimumHeight)
g.addEdge(0, 3)
g.addEdge(1, 3)
g.addEdge(2, 3)
g.addEdge(4, 3)
g.addEdge(5, 4)
# Function call
res = g.rootForMinimumHeight()
for i in res:
print (i,end=" ")
# This code is contributed by Nikhil Kumar Singh(nickzuck_007)
输出
3 4
由于我们访问每个节点一次,因此解决方案的总时间复杂度为 O(n)。