📜  查找树中距每个节点最远的节点

📅  最后修改于: 2021-05-08 18:06:26             🧑  作者: Mango

给定一棵树,任务是找到该树中从每个节点到另一个节点的最远节点。

例子:

方法:
首先,我们必须找到直径的两个端点,然后找到该端点,我们将选择一个任意顶点并从该任意顶点中找到最远的节点,并且该节点将是直径的一端,然后使其成为最远的根从它的节点,这将是直径的另一端。现在,对于每个节点,最远的节点将是树直径的这两个最终顶点之一。

为什么行得通?
令x和y为树的直径的两个端点,一个随机顶点为u。让距离u最远的顶点是v,而不是x或y。由于v离u最远,因此将形成一个新的直径,其最终顶点为x,v或y,v的长度更大,但是树的直径唯一长,因此不可能并且距u最远的顶点必须为x或y。

下面是上述方法的实现:

C++
// C++ implementation to find the
// farthest node from each vertex
// of the tree
 
#include 
 
using namespace std;
 
#define N 10000
 
// Adjacency list to store edges
vector adj[N];
 
int lvl[N], dist1[N], dist2[N];
 
// Add edge between
// U and V in tree
void AddEdge(int u, int v)
{
    // Edge from U to V
    adj[u].push_back(v);
     
    // Edge from V to U
    adj[v].push_back(u);
}
 
int end1, end2, maxi;
 
// DFS to find the first
// End Node of diameter
void findFirstEnd(int u, int p)
{
    // Calculating level of nodes
    lvl[u] = 1 + lvl[p];
    if (lvl[u] > maxi) {
        maxi = lvl[u];
        end1 = u;
    }
     
    for (int i = 0; i < adj[u].size(); i++) {
         
        // Go in opposite
        // direction of parent
        if (adj[u][i] != p) {
            findFirstEnd(adj[u][i], u);
        }
    }
}
 
// Function to clear the levels
// of the nodes
void clear(int n)
{
    // set all value of lvl[]
    // to 0 for next dfs
    for (int i = 0; i <= n; i++) {
        lvl[i] = 0;
    }
     
    // Set maximum with 0
    maxi = 0;
    dist1[0] = dist2[0] = -1;
}
 
// DFS will calculate second
// end of the diameter
void findSecondEnd(int u, int p)
{
    // Calculating level of nodes
    lvl[u] = 1 + lvl[p];
    if (lvl[u] > maxi) {
        maxi = lvl[u];
         
        // Store the node with
        // maximum depth from end1
        end2 = u;
    }
 
    for (int i = 0; i < adj[u].size(); i++) {
        // Go in opposite
        // direction of parent
        if (adj[u][i] != p) {
            findSecondEnd(adj[u][i], u);
        }
    }
}
 
// Function to find the distance
// of the farthest distant node
void findDistancefromFirst(int u, int p)
{
    // Storing distance from
    // end1 to node u
    dist1[u] = 1 + dist1[p];
    for (int i = 0; i < adj[u].size(); i++) {
        if (adj[u][i] != p) {
            findDistancefromFirst(adj[u][i], u);
        }
    }
}
 
// Function to find the distance
// of nodes from second end of diameter
void findDistancefromSecond(int u, int p)
{
    // storing distance from end2 to node u
    dist2[u] = 1 + dist2[p];
    for (int i = 0; i < adj[u].size(); i++) {
        if (adj[u][i] != p) {
            findDistancefromSecond(adj[u][i], u);
        }
    }
}
 
void findNodes(){
    int n = 5;
 
    // Joining Edge between two
    // nodes of the tree
    AddEdge(1, 2);
    AddEdge(1, 3);
    AddEdge(3, 4);
    AddEdge(3, 5);
 
    // Find the one end of
    // the diameter of tree
    findFirstEnd(1, 0);
    clear(n);
     
    // Find the other end
    // of the diameter of tree
    findSecondEnd(end1, 0);
 
    // Find the distance
    // to each node from end1
    findDistancefromFirst(end1, 0);
 
    // Find the distance to
    // each node from end2
    findDistancefromSecond(end2, 0);
 
    for (int i = 1; i <= n; i++) {
        int x = dist1[i];
        int y = dist2[i];
         
        // Comparing distance between
        // the two ends of diameter
        if (x >= y) {
            cout << end1 << ' ';
        }
        else {
            cout << end2 << ' ';
        }
    }
}
 
// Driver code
int main()
{
    // Function Call
    findNodes();
 
    return 0;
}


Java
// Java implementation to find the
// farthest node from each vertex
// of the tree
import java.util.*;
 
class GFG{
 
static int N = 10000;
 
// Adjacency list to store edges
@SuppressWarnings("unchecked")
static Vector[] adj = new Vector[N];
 
static int[] lvl = new int[N],
           dist1 = new int[N],
           dist2 = new int[N];
 
// Add edge between
// U and V in tree
static void AddEdge(int u, int v)
{
     
    // Edge from U to V
    adj[u].add(v);
 
    // Edge from V to U
    adj[v].add(u);
}
 
static int end1, end2, maxi;
 
// DFS to find the first
// End Node of diameter
static void findFirstEnd(int u, int p)
{
     
    // Calculating level of nodes
    lvl[u] = 1 + lvl[p];
    if (lvl[u] > maxi)
    {
        maxi = lvl[u];
        end1 = u;
    }
 
    for(int i = 0; i < adj[u].size(); i++)
    {
         
        // Go in opposite
        // direction of parent
        if (adj[u].elementAt(i) != p)
        {
            findFirstEnd(adj[u].elementAt(i), u);
        }
    }
}
 
// Function to clear the levels
// of the nodes
static void clear(int n)
{
     
    // Set all value of lvl[]
    // to 0 for next dfs
    for(int i = 0; i <= n; i++)
    {
        lvl[i] = 0;
    }
 
    // Set maximum with 0
    maxi = 0;
    dist1[0] = dist2[0] = -1;
}
 
// DFS will calculate second
// end of the diameter
static void findSecondEnd(int u, int p)
{
     
    // Calculating level of nodes
    lvl[u] = 1 + lvl[p];
    if (lvl[u] > maxi)
    {
        maxi = lvl[u];
 
        // Store the node with
        // maximum depth from end1
        end2 = u;
    }
 
    for(int i = 0; i < adj[u].size(); i++)
    {
         
        // Go in opposite
        // direction of parent
        if (adj[u].elementAt(i) != p)
        {
            findSecondEnd(adj[u].elementAt(i), u);
        }
    }
}
 
// Function to find the distance
// of the farthest distant node
static void findDistancefromFirst(int u, int p)
{
     
    // Storing distance from
    // end1 to node u
    dist1[u] = 1 + dist1[p];
    for(int i = 0; i < adj[u].size(); i++)
    {
        if (adj[u].elementAt(i) != p)
        {
            findDistancefromFirst(
                adj[u].elementAt(i), u);
        }
    }
}
 
// Function to find the distance
// of nodes from second end of diameter
static void findDistancefromSecond(int u, int p)
{
     
    // Storing distance from end2 to node u
    dist2[u] = 1 + dist2[p];
    for(int i = 0; i < adj[u].size(); i++)
    {
        if (adj[u].elementAt(i) != p)
        {
            findDistancefromSecond(
                adj[u].elementAt(i), u);
        }
    }
}
 
static void findNodes()
{
    int n = 5;
 
    // Joining Edge between two
    // nodes of the tree
    AddEdge(1, 2);
    AddEdge(1, 3);
    AddEdge(3, 4);
    AddEdge(3, 5);
 
    // Find the one end of
    // the diameter of tree
    findFirstEnd(1, 0);
    clear(n);
 
    // Find the other end
    // of the diameter of tree
    findSecondEnd(end1, 0);
 
    // Find the distance
    // to each node from end1
    findDistancefromFirst(end1, 0);
 
    // Find the distance to
    // each node from end2
    findDistancefromSecond(end2, 0);
 
    for(int i = 1; i <= n; i++)
    {
        int x = dist1[i];
        int y = dist2[i];
 
        // Comparing distance between
        // the two ends of diameter
        if (x >= y)
        {
            System.out.print(end1 + " ");
        }
        else
        {
            System.out.print(end2 + " ");
        }
    }
}
 
// Driver Code
public static void main(String[] args)
{
    for(int i = 0; i < N; i++)
    {
        adj[i] = new Vector<>();
    }
 
    // Function call
    findNodes();
}
}
 
// This code is contributed by sanjeev2552


Python3
# Python3 implementation to find the
# farthest node from each vertex
# of the tree
  
# Add edge between
# U and V in tree
def AddEdge(u, v):
     
    global adj
     
    # Edge from U to V
    adj[u].append(v)
  
    # Edge from V to U
    adj[v].append(u)
  
# DFS to find the first
# End Node of diameter
def findFirstEnd(u, p):
     
    global lvl, adj, end1, maxi
     
    # Calculating level of nodes
    lvl[u] = 1 + lvl[p]
     
    if (lvl[u] > maxi):
        maxi = lvl[u]
        end1 = u
  
    for i in range(len(adj[u])):
  
        # Go in opposite
        # direction of parent
        if (adj[u][i] != p):
            findFirstEnd(adj[u][i], u)
  
# Function to clear the levels
# of the nodes
def clear(n):
     
    global lvl, dist1, dist2
     
    # Set all value of lvl[]
    # to 0 for next dfs
    for i in range(n + 1):
        lvl[i] = 0
  
    # Set maximum with 0
    maxi = 0
    dist1[0] = dist2[0] = -1
  
# DFS will calculate second
# end of the diameter
def findSecondEnd(u, p):
     
    global lvl, adj, maxi, end2
     
    # Calculating level of nodes
    lvl[u] = 1 + lvl[p]
     
    if (lvl[u] > maxi):
        maxi = lvl[u]
  
        # Store the node with
        # maximum depth from end1
        end2 = u
  
    for i in range(len(adj[u])):
         
        # Go in opposite
        # direction of parent
        if (adj[u][i] != p):
            findSecondEnd(adj[u][i], u)
  
# Function to find the distance
# of the farthest distant node
def findDistancefromFirst(u, p):
     
    global dist1, adj
     
    # Storing distance from
    # end1 to node u
    dist1[u] = 1 + dist1[p]
     
    for i in range(len(adj[u])):
        if (adj[u][i] != p):
            findDistancefromFirst(adj[u][i], u)
  
# Function to find the distance
# of nodes from second end of diameter
def findDistancefromSecond(u, p):
     
    global dist2, adj
     
    # Storing distance from end2 to node u
    dist2[u] = 1 + dist2[p]
     
    for i in range(len(adj[u])):
        if (adj[u][i] != p):
            findDistancefromSecond(adj[u][i], u)
  
def findNodes():
     
    global adj, lvl, dist1, dist2, end1, end2, maxi
    n = 5
  
    # Joining Edge between two
    # nodes of the tree
    AddEdge(1, 2)
    AddEdge(1, 3)
    AddEdge(3, 4)
    AddEdge(3, 5)
  
    # Find the one end of
    # the diameter of tree
    findFirstEnd(1, 0)
    clear(n)
  
    # Find the other end
    # of the diameter of tree
    findSecondEnd(end1, 0)
  
    # Find the distance
    # to each node from end1
    findDistancefromFirst(end1, 0)
  
    # Find the distance to
    # each node from end2
    findDistancefromSecond(end2, 0)
  
    for i in range(1, n + 1):
        x = dist1[i]
        y = dist2[i]
  
        # Comparing distance between
        # the two ends of diameter
        if (x >= y):
            print(end1, end = " ")
        else:
            print(end2, end = " ")
  
# Driver code
if __name__ == '__main__':
     
    adj = [[] for i in range(10000)]
    lvl = [0 for i in range(10000)]
    dist1 = [-1 for i in range(10000)]
    dist2 = [-1 for i in range(10000)]
    end1, end2, maxi = 0, 0, 0
     
    # Function Call
    findNodes()
 
# This code is contributed by mohit kumar 29


C#
// C# implementation to find the
// farthest node from each vertex
// of the tree
using System;
using System.Collections.Generic;
 
class GFG{
 
static int N = 10000;
 
// Adjacency list to store edges
static List[] adj = new List[N];
 
static int[] lvl = new int[N],
           dist1 = new int[N],
           dist2 = new int[N];
 
// Add edge between
// U and V in tree
static void AddEdge(int u, int v)
{
     
    // Edge from U to V
    adj[u].Add(v);
 
    // Edge from V to U
    adj[v].Add(u);
}
 
static int end1, end2, maxi;
 
// DFS to find the first
// End Node of diameter
static void findFirstEnd(int u, int p)
{
     
    // Calculating level of nodes
    lvl[u] = 1 + lvl[p];
     
    if (lvl[u] > maxi)
    {
        maxi = lvl[u];
        end1 = u;
    }
 
    for(int i = 0; i < adj[u].Count; i++)
    {
         
        // Go in opposite
        // direction of parent
        if (adj[u][i] != p)
        {
            findFirstEnd(adj[u][i], u);
        }
    }
}
 
// Function to clear the levels
// of the nodes
static void clear(int n)
{
     
    // Set all value of lvl[]
    // to 0 for next dfs
    for(int i = 0; i <= n; i++)
    {
        lvl[i] = 0;
    }
 
    // Set maximum with 0
    maxi = 0;
    dist1[0] = dist2[0] = -1;
}
 
// DFS will calculate second
// end of the diameter
static void findSecondEnd(int u, int p)
{
     
    // Calculating level of nodes
    lvl[u] = 1 + lvl[p];
     
    if (lvl[u] > maxi)
    {
        maxi = lvl[u];
 
        // Store the node with
        // maximum depth from end1
        end2 = u;
    }
 
    for(int i = 0; i < adj[u].Count; i++)
    {
         
        // Go in opposite
        // direction of parent
        if (adj[u][i] != p)
        {
            findSecondEnd(adj[u][i], u);
        }
    }
}
 
// Function to find the distance
// of the farthest distant node
static void findDistancefromFirst(int u, int p)
{
     
    // Storing distance from
    // end1 to node u
    dist1[u] = 1 + dist1[p];
     
    for(int i = 0; i < adj[u].Count; i++)
    {
        if (adj[u][i] != p)
        {
            findDistancefromFirst(adj[u][i], u);
        }
    }
}
 
// Function to find the distance
// of nodes from second end of diameter
static void findDistancefromSecond(int u, int p)
{
     
    // Storing distance from end2 to node u
    dist2[u] = 1 + dist2[p];
     
    for(int i = 0; i < adj[u].Count; i++)
    {
        if (adj[u][i] != p)
        {
            findDistancefromSecond(adj[u][i], u);
        }
    }
}
 
static void findNodes()
{
    int n = 5;
 
    // Joining Edge between two
    // nodes of the tree
    AddEdge(1, 2);
    AddEdge(1, 3);
    AddEdge(3, 4);
    AddEdge(3, 5);
 
    // Find the one end of
    // the diameter of tree
    findFirstEnd(1, 0);
    clear(n);
 
    // Find the other end
    // of the diameter of tree
    findSecondEnd(end1, 0);
 
    // Find the distance
    // to each node from end1
    findDistancefromFirst(end1, 0);
 
    // Find the distance to
    // each node from end2
    findDistancefromSecond(end2, 0);
 
    for(int i = 1; i <= n; i++)
    {
        int x = dist1[i];
        int y = dist2[i];
 
        // Comparing distance between
        // the two ends of diameter
        if (x >= y)
        {
            Console.Write(end1 + " ");
        }
        else
        {
            Console.Write(end2 + " ");
        }
    }
}
 
// Driver Code
public static void Main(String[] args)
{
    for(int i = 0; i < N; i++)
    {
        adj[i] = new List();
    }
 
    // Function call
    findNodes();
}
}
 
// This code is contributed by gauravrajput1


输出:
4 4 2 2 2

时间复杂度:O(V + E)