给定一个由N 个节点组成的树,这些节点的值在[0, N – 1]和(N – 1) 条边的范围内,以及两个节点X和Y ,任务是找到树中可能路径的数量,使得节点X不会出现在路径中的节点Y之前。
例子:
Input: N = 5, A = 2, B = 0, Edges[][] = { {0, 1}, {1, 2}, {1, 3}, {0, 4} }
Output: 18
Explanation:
Since (X, Y) and (Y, X) are being considered different, so the count of all possible paths connecting any two pairs of vertices = 2 * 5C2 = 20.
Out of these 20 pairs, those paths cannot be chosen, which consist of both nodes 2 and 0 as well as Node 2 appearing before Node 0.
There are two such paths (colored as green) which are shown below:
So there are total 20 – 2 = 18 such paths.
Input: N = 9, X = 5, Y = 3, Edges[][] = { {0, 2}, {1, 2}, {2, 3}, {3, 4}, {4, 6}, {4, 5}, {5, 7}, {5, 8} }
Output: 60
Explanation:
Since (X, Y) and (Y, X) are being considered different, so the count of all possible paths connecting any two pairs of vertices = N * (N – 1) = 9 * 8 = 72.
On observing the diagram below, any path starting from a Node in the subtree of Node 5, denoted by black, connecting to the vertices passing through the Node 3, denoted by green, will always have 5 appearing before 3 in the path.
Therefore, total number of possible paths = (Total Nodes grouped in black) * (Total Nodes grouped in green) = 3 * 4 = 12.
Therefore, the final answer = 72 – 12 = 60
方法:
这个想法是找到节点对的组合,在连接它们的路径中,节点 X 总是出现在节点 Y 之前。然后,从可能的节点对的总数中减去这些对的数量= N C 2 。将节点Y视为根节点。现在,首先遇到X然后遇到Y 的任何路径都从节点X的子树中的节点开始,并在节点Y的子树中的一个节点处结束,但不在节点W的子树中,其中W是节点Y位于这些路径中的X和Y之间。
因此,最终答案可以通过以下方式计算:
Count = N * (N – 1) – size_of_subtree(X) * (size_of_subtree(Y) – size_of_subtree(W))
如果将Y作为树的根。然后, size_of_subtree(Y) = N 。
Count = N * (N – 1) – size_of_subtree(X) * (N- size_of_subtree(W))
请按照以下步骤解决问题:
- 初始化数组subtree_size [] 、 visited []和check_subtree []每个大小为N + 1 。将visited [] 的元素初始化为0 。
- 以Y为根节点执行DFS遍历,为每个节点填充check_subtree[]和subtree_size[] 。 check_subtree[]检查当前节点的子树是否包含节点X。
- 找到Y的子节点(比如节点 v) ,它位于从X到Y的路径中。初始化一个整数变量说差异。
- 将(节点总数 – subtree_size[v] )分配给差异。
- 返回(N * (N – 1) ) – (subtree_size[A] * (difference))作为答案。
下面是上述方法的实现:
C++
// C++ Program to implement
// the above approach
#include
#define int long long int
using namespace std;
// Maximum number of nodes
const int NN = 3e5;
// Vector to store the tree
vector G[NN + 1];
// Function to perform DFS Traversal
int dfs(int node, int A, int* subtree_size,
int* visited, int* check_subtree)
{
// Mark the node as visited
visited[node] = true;
// Initialize the subtree size
// of each node as 1
subtree_size[node] = 1;
// If the node is same as A
if (node == A) {
// Mark check_subtree[node] as true
check_subtree[node] = true;
}
// Otherwise
else
check_subtree[node] = false;
// Iterate over the adjacent nodes
for (int v : G[node]) {
// If the adjacent node
// is not visited
if (!visited[v]) {
// Update the size of the
// subtree of current node
subtree_size[node]
+= dfs(v, A, subtree_size,
visited, check_subtree);
// Check if the subtree of
// current node contains node A
check_subtree[node] = check_subtree[node]
| check_subtree[v];
}
}
// Return size of subtree of node
return subtree_size[node];
}
// Function to add edges to the tree
void addedge(int node1, int node2)
{
G[node1].push_back(node2);
G[node2].push_back(node1);
}
// Function to calculate the number of
// possible paths
int numberOfPairs(int N, int B, int A)
{
// Stores the size of subtree
// of each node
int subtree_size[N + 1];
// Stores which nodes are
// visited
int visited[N + 1];
// Initialise all nodes as unvisited
memset(visited, 0, sizeof(visited));
// Stores if the subtree of
// a node contains node A
int check_subtree[N + 1];
// DFS Call
dfs(B, A, subtree_size,
visited, check_subtree);
// Stores the difference between
// total number of nodes and
// subtree size of an immediate
// child of Y lies between the
// path from A to B
int difference;
// Iterate over the adjacent nodes B
for (int v : G[B]) {
// If the node is in the path
// from A to B
if (check_subtree[v]) {
// Calcualte the difference
difference = N - subtree_size[v];
break;
}
}
// Return the final answer
return (N * (N - 1))
- difference * (subtree_size[A]);
}
// Driver Code
int32_t main()
{
int N = 9;
int X = 5, Y = 3;
// Insert Edges
addedge(0, 2);
addedge(1, 2);
addedge(2, 3);
addedge(3, 4);
addedge(4, 6);
addedge(4, 5);
addedge(5, 7);
addedge(5, 8);
cout << numberOfPairs(N, Y, X);
return 0;
}
Java
// Java Program to implement
// the above approach
import java.util.*;
class GFG{
// Maximum number of nodes
static int NN = (int) 3e5;
// Vector to store the tree
static Vector []G = new Vector[NN + 1];
// Function to perform DFS Traversal
static int dfs(int node, int A, int[] subtree_size,
int[] visited, int[] check_subtree)
{
// Mark the node as visited
visited[node] = 1;
// Initialize the subtree size
// of each node as 1
subtree_size[node] = 1;
// If the node is same as A
if (node == A)
{
// Mark check_subtree[node] as true
check_subtree[node] = 1;
}
// Otherwise
else
check_subtree[node] = 0;
// Iterate over the adjacent nodes
for (int v : G[node])
{
// If the adjacent node
// is not visited
if (visited[v] == 0)
{
// Update the size of the
// subtree of current node
subtree_size[node] += dfs(v, A, subtree_size,
visited, check_subtree);
// Check if the subtree of
// current node contains node A
check_subtree[node] = check_subtree[node] |
check_subtree[v];
}
}
// Return size of subtree of node
return subtree_size[node];
}
// Function to add edges to the tree
static void addedge(int node1, int node2)
{
G[node1].add(node2);
G[node2].add(node1);
}
// Function to calculate the number of
// possible paths
static int numberOfPairs(int N, int B, int A)
{
// Stores the size of subtree
// of each node
int []subtree_size = new int[N + 1];
// Stores which nodes are
// visited
int []visited = new int[N + 1];
// Stores if the subtree of
// a node contains node A
int []check_subtree = new int[N + 1];
// DFS Call
dfs(B, A, subtree_size,
visited, check_subtree);
// Stores the difference between
// total number of nodes and
// subtree size of an immediate
// child of Y lies between the
// path from A to B
int difference = 0;
// Iterate over the adjacent nodes B
for (int v : G[B])
{
// If the node is in the path
// from A to B
if (check_subtree[v] > 0)
{
// Calcualte the difference
difference = N - subtree_size[v];
break;
}
}
// Return the final answer
return (N * (N - 1)) -
difference * (subtree_size[A]);
}
// Driver Code
public static void main(String[] args)
{
int N = 9;
int X = 5, Y = 3;
for (int i = 0; i < G.length; i++)
G[i] = new Vector();
// Insert Edges
addedge(0, 2);
addedge(1, 2);
addedge(2, 3);
addedge(3, 4);
addedge(4, 6);
addedge(4, 5);
addedge(5, 7);
addedge(5, 8);
System.out.print(numberOfPairs(N, Y, X));
}
}
// This code is contributed by sapnasingh4991
Python3
# Python3 program to implement
# the above approach
# Maximum number of nodes
NN = int(3e5)
# Vector to store the tree
G = []
for i in range(NN + 1):
G.append([])
# Function to perform DFS Traversal
def dfs(node, A, subtree_size,
visited, check_subtree):
# Mark the node as visited
visited[node] = True
# Initialize the subtree size
# of each node as 1
subtree_size[node] = 1
# If the node is same as A
if (node == A):
# Mark check_subtree[node] as true
check_subtree[node] = True
# Otherwise
else:
check_subtree[node] = False
# Iterate over the adjacent nodes
for v in G[node]:
# If the adjacent node
# is not visited
if (not visited[v]):
# Update the size of the
# subtree of current node
subtree_size[node] += dfs(v, A,
subtree_size,
visited,
check_subtree)
# Check if the subtree of
# current node contains node A
check_subtree[node] = (check_subtree[node] |
check_subtree[v])
# Return size of subtree of node
return subtree_size[node]
# Function to add edges to the tree
def addedge(node1, node2):
G[node1] += [node2]
G[node2] += [node1]
# Function to calculate the number of
# possible paths
def numberOfPairs(N, B, A):
# Stores the size of subtree
# of each node
subtree_size = [0] * (N + 1)
# Stores which nodes are
# visited
visited = [0] * (N + 1)
# Stores if the subtree of
# a node contains node A
check_subtree = [0] * (N + 1)
# DFS Call
dfs(B, A, subtree_size,
visited, check_subtree)
# Stores the difference between
# total number of nodes and
# subtree size of an immediate
# child of Y lies between the
# path from A to B
difference = 0
# Iterate over the adjacent nodes B
for v in G[B]:
# If the node is in the path
# from A to B
if (check_subtree[v]):
# Calcualte the difference
difference = N - subtree_size[v]
break
# Return the final answer
return ((N * (N - 1)) -
difference * (subtree_size[A]))
# Driver Code
N = 9
X = 5
Y = 3
# Insert Edges
addedge(0, 2)
addedge(1, 2)
addedge(2, 3)
addedge(3, 4)
addedge(4, 6)
addedge(4, 5)
addedge(5, 7)
addedge(5, 8)
# Function call
print(numberOfPairs(N, Y, X))
# This code is contributed by Shivam Singh
C#
// C# Program to implement
// the above approach
using System;
using System.Collections.Generic;
class GFG{
// Maximum number of nodes
static int NN = (int) 3e5;
// List to store the tree
static List []G = new List[NN + 1];
// Function to perform DFS Traversal
static int dfs(int node, int A, int[] subtree_size,
int[] visited, int[] check_subtree)
{
// Mark the node as visited
visited[node] = 1;
// Initialize the subtree size
// of each node as 1
subtree_size[node] = 1;
// If the node is same as A
if (node == A)
{
// Mark check_subtree[node] as true
check_subtree[node] = 1;
}
// Otherwise
else
check_subtree[node] = 0;
// Iterate over the adjacent nodes
foreach (int v in G[node])
{
// If the adjacent node
// is not visited
if (visited[v] == 0)
{
// Update the size of the
// subtree of current node
subtree_size[node] += dfs(v, A, subtree_size,
visited, check_subtree);
// Check if the subtree of
// current node contains node A
check_subtree[node] = check_subtree[node] |
check_subtree[v];
}
}
// Return size of subtree of node
return subtree_size[node];
}
// Function to add edges to the tree
static void addedge(int node1, int node2)
{
G[node1].Add(node2);
G[node2].Add(node1);
}
// Function to calculate the number of
// possible paths
static int numberOfPairs(int N, int B, int A)
{
// Stores the size of subtree
// of each node
int []subtree_size = new int[N + 1];
// Stores which nodes are
// visited
int []visited = new int[N + 1];
// Stores if the subtree of
// a node contains node A
int []check_subtree = new int[N + 1];
// DFS Call
dfs(B, A, subtree_size,
visited, check_subtree);
// Stores the difference between
// total number of nodes and
// subtree size of an immediate
// child of Y lies between the
// path from A to B
int difference = 0;
// Iterate over the adjacent nodes B
foreach (int v in G[B])
{
// If the node is in the path
// from A to B
if (check_subtree[v] > 0)
{
// Calcualte the difference
difference = N - subtree_size[v];
break;
}
}
// Return the readonly answer
return (N * (N - 1)) -
difference * (subtree_size[A]);
}
// Driver Code
public static void Main(String[] args)
{
int N = 9;
int X = 5, Y = 3;
for (int i = 0; i < G.Length; i++)
G[i] = new List();
// Insert Edges
addedge(0, 2);
addedge(1, 2);
addedge(2, 3);
addedge(3, 4);
addedge(4, 6);
addedge(4, 5);
addedge(5, 7);
addedge(5, 8);
Console.Write(numberOfPairs(N, Y, X));
}
}
// This code is contributed by sapnasingh4991
Javascript
60
时间复杂度: O(N)
辅助空间: O(N)
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。