📜  给出最小高度的树的根

📅  最后修改于: 2022-05-13 01:57:54.146000             🧑  作者: Mango

给出最小高度的树的根

给定一个具有树特征的无向图。可以选择任何节点作为根,任务是只找到那些最小化树高度的节点。

例子:
在下图中,所有节点都被一一设为根,我们可以看到当 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)。