📌  相关文章
📜  在N元树的中心找到节点

📅  最后修改于: 2021-05-04 07:07:41             🧑  作者: Mango

先决条件:

  • 一元树的直径
  • 图中两个节点之间的路径

给定一棵N元树,其中N个节点的编号从0到N-1,并列出了无向边的列表,任务是在给定树的中心找到一个或多个节点。

例子:

方法:可以看出,最大偏心距的路径是树的直径。因此,树直径的中心也将是树的中心。

证明:

  • 现在,如果直径包含奇数个节点,则仅存在1个中心(也称为Central Tree )。
  • 如果直径由偶数个节点组成,则有2个中心节点(也称为双中心树)。

下面是上述方法的实现:

C++
// C++ implementation of
// the above approach
 
#include 
using namespace std;
 
// To create tree
map > tree;
 
// Function to store the path
// from given vertex to the target
// vertex in a vector path
bool getDiameterPath(int vertex,
                     int targetVertex,
                     int parent,
                     vector& path)
{
 
    // If the target node is found,
    // push it into path vector
    if (vertex == targetVertex) {
 
        path.push_back(vertex);
        return true;
    }
 
    for (auto i : tree[vertex]) {
 
        // To prevent visiting a
        // node already visited
        if (i == parent)
            continue;
 
        // Recursive call to the neighbours
        // of current node inorder
        // to get the path
        if (getDiameterPath(i, targetVertex,
                            vertex, path)) {
            path.push_back(vertex);
            return true;
        }
    }
 
    return false;
}
 
// Function to obtain and return the
// farthest node from a given vertex
void farthestNode(int vertex, int parent,
                  int height, int& maxHeight,
                  int& maxHeightNode)
{
 
    // If the current height is maximum
    // so far, then save the current node
    if (height > maxHeight) {
        maxHeight = height;
        maxHeightNode = vertex;
    }
 
    // Iterate over all the neighbours
    // of current node
    for (auto i : tree[vertex]) {
        // This is to prevent visiting
        // a already visited node
        if (i == parent)
            continue;
 
        // Next call will be at 1 height
        // higher than our current height
        farthestNode(i, vertex,
                     height + 1,
                     maxHeight,
                     maxHeightNode);
    }
}
 
// Function to add edges
void addedge(int a, int b)
{
    tree[a].push_back(b);
    tree[b].push_back(a);
}
 
void FindCentre(int n)
{
    // Now we will find the 1st farthest
    // node from 0(any arbitary node)
 
    // Perform DFS from 0 and update
    // the maxHeightNode to obtain
    // the farthest node from 0
 
    // Reset to -1
    int maxHeight = -1;
 
    // Reset to -1
    int maxHeightNode = -1;
 
    farthestNode(0, -1, 0, maxHeight,
                 maxHeightNode);
 
    // Stores one end of the diamter
    int leaf1 = maxHeightNode;
 
    // Similarly the other end of
    // the diameter
 
    // Reset the maxHeight
    maxHeight = -1;
    farthestNode(maxHeightNode,
                 -1, 0, maxHeight,
                 maxHeightNode);
 
    // Stores the second end
    // of the diameter
    int leaf2 = maxHeightNode;
 
    // Store the diameter into
    // the vector path
    vector path;
 
    // Diamter is equal to the
    // path between the two farthest
    // nodes leaf1 and leaf2
    getDiameterPath(leaf1, leaf2,
                    -1, path);
 
    int pathSize = path.size();
 
    if (pathSize % 2) {
        cout << path[pathSize / 2]
             << endl;
    }
    else {
        cout << path[pathSize / 2]
             << ", "
             << path[(pathSize - 1) / 2]
             << endl;
    }
}
 
// Driver Code
int main()
{
 
    int N = 4;
    addedge(1, 0);
    addedge(1, 2);
    addedge(1, 3);
 
    FindCentre(N);
 
    return 0;
}


Java
// Java implementation of
// the above approach
import java.util.*;
 
class GFG{
 
// To create tree
static Map> tree;
static ArrayList path;
static int maxHeight, maxHeightNode;
 
// Function to store the path
// from given vertex to the target
// vertex in a vector path
static boolean getDiameterPath(int vertex,
                               int targetVertex,
                               int parent,
                               ArrayList path)
{
 
    // If the target node is found,
    // push it into path vector
    if (vertex == targetVertex)
    {
        path.add(vertex);
        return true;
    }
 
    for(Integer i : tree.get(vertex))
    {
         
        // To prevent visiting a
        // node already visited
        if (i == parent)
            continue;
 
        // Recursive call to the neighbours
        // of current node inorder
        // to get the path
        if (getDiameterPath(i, targetVertex,
                            vertex, path))
        {
            path.add(vertex);
            return true;
        }
    }
    return false;
}
 
// Function to obtain and return the
// farthest node from a given vertex
static void farthestNode(int vertex, int parent,
                         int height)
{
     
    // If the current height is maximum
    // so far, then save the current node
    if (height > maxHeight)
    {
        maxHeight = height;
        maxHeightNode = vertex;
    }
 
    // Iterate over all the neighbours
    // of current node
    if (tree.get(vertex) != null)
        for(Integer i : tree.get(vertex))
        {
             
            // This is to prevent visiting
            // a already visited node
            if (i == parent)
                continue;
 
            // Next call will be at 1 height
            // higher than our current height
            farthestNode(i, vertex,
                         height + 1);
        }
}
 
// Function to add edges
static void addedge(int a, int b)
{
    if (tree.get(a) == null)
        tree.put(a, new ArrayList<>());
 
    tree.get(a).add(b);
 
    if (tree.get(b) == null)
        tree.put(b, new ArrayList<>());
 
    tree.get(b).add(a);
}
 
static void FindCentre(int n)
{
     
    // Now we will find the 1st farthest
    // node from 0(any arbitary node)
 
    // Perform DFS from 0 and update
    // the maxHeightNode to obtain
    // the farthest node from 0
 
    // Reset to -1
    maxHeight = -1;
 
    // Reset to -1
    maxHeightNode = -1;
 
    farthestNode(0, -1, 0);
 
    // Stores one end of the diamter
    int leaf1 = maxHeightNode;
 
    // Similarly the other end of
    // the diameter
 
    // Reset the maxHeight
    maxHeight = -1;
    farthestNode(maxHeightNode,
                 -1, 0);
 
    // Stores the second end
    // of the diameter
    int leaf2 = maxHeightNode;
 
    // Store the diameter into
    // the vector path
    path = new ArrayList<>();
 
    // Diameter is equal to the
    // path between the two farthest
    // nodes leaf1 and leaf2
    getDiameterPath(leaf1, leaf2,
                    -1, path);
 
    int pathSize = path.size();
 
    if (pathSize % 2 == 1)
    {
        System.out.println(path.get(pathSize / 2));
    }
    else {
        System.out.println(path.get(pathSize / 2) +
                    ", " + path.get((pathSize - 1) / 2));
    }
}
 
// Driver code
public static void main(String[] args)
{
    int N = 4;
 
    tree = new HashMap<>();
    addedge(1, 0);
    addedge(1, 2);
    addedge(1, 3);
 
    FindCentre(N);
}
}
 
// This code is contributed by offbeat


输出:
1



时间复杂度: O(N)
辅助空间: O(N)