给定一棵树,任务是找到该树中从每个节点到另一个节点的最远节点。
例子:
Input: Given Adjacency List of Below Tree:
Output:
Farthest node from node 1: 6
Farthest node from node 2: 6
Farthest node from node 3: 6
Farthest node from node 4: 6
Farthest node from node 5: 1
Farthest node from node 6: 1
Input:
Output:
Farthest node from node 1: 4
Farthest node from node 2: 7
Farthest node from node 3: 4
Farthest node from node 4: 7
Farthest node from node 5: 7
Farthest node from node 6: 4
Farthest node from node 7: 4
方法:
首先,我们必须找到直径的两个端点,然后找到该端点,我们将选择一个任意顶点并从该任意顶点中找到最远的节点,并且该节点将是直径的一端,然后使其成为最远的根从它的节点,这将是直径的另一端。现在,对于每个节点,最远的节点将是树直径的这两个最终顶点之一。
为什么行得通?
令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)