给定一棵树,它有N个顶点,编号从0到N – 1,有 M 条边, Q查询的形式为{U, V},这样树中U和V之间就有一条直接边。每个查询的任务是从包含给定节点对之间的边的给定树中的任何可能的无序顶点对之间找到所有可能的最短路径。
例子:
Input: N = 6, M[] ={{0, 1}, {0, 2}, {1, 3}, {3, 4}, {3, 5}}, queries[] = {{1, 3}, {0, 2}}
0
/ \
1 2
/
3
/ \
4 5
Output:
9
5
Explanation:
Query 1: The edge (1, 3) lies in the paths {1, 3), (1, 3, 4), (1, 3, 5), (0, 3), (0, 4), (0, 5), (2, 3), (2, 4) and (2, 5).
Query 2: The edge (0, 2) lies in the paths (2, 0), (2, 1), (2, 3), (2, 4) and (2, 5).
Input: N = 6, M[] ={{0, 1}, {0, 2}, {2, 3}, {1, 4}, {1, 5}}, queries[] = {{1, 5}, {0, 2}}
0
/ \
1 2
/ \ /
4 5 3
Output:
5
8
方法:该问题可以基于以下观察来解决:对于任何查询{U, V},如果其中一个节点位于树中,则树中任何一对节点之间的最短路径将包含给定边(U, V) U 的子树,另一个节点位于剩余的树中。因此,所需的对数为:
Count of shortest paths containing (U, V) as an edge = subtreeSize(U) * (N – subtreeSize(V)).
因此,请按照以下步骤解决问题:
- 从根节点开始对树执行深度优先搜索遍历。
- 对于每个节点,将节点数存储在其子树中(包括节点)。
- 迭代每个查询 (U, V) 并计算:
min( subtreeSize(U), subtreeSize(V)) * ( N – min( subtreeSize(U), subtreeSize(V)) )
下面是上述方法的实现:
C++
// C++ implementation for the above approach
#include
using namespace std;
const int sz = 1e5;
// Adjacency list to
// represent the tree
vector tree[sz];
// Number of vertices
int n;
// Mark visited/ unvisited
// vertices
bool vis[sz];
// Stores the subtree size
// of the corresponding nodes
int subtreeSize[sz];
// Function to create an
// edge between two vertices
void addEdge(int a, int b)
{
// Add a to b's list
tree[a].push_back(b);
// Add b to a's list
tree[b].push_back(a);
}
// Function to perform DFS
void dfs(int x)
{
// Mark the vertex
// visited
vis[x] = true;
// Include the node in
// the subtree
subtreeSize[x] = 1;
// Traverse all its children
for (auto i : tree[x]) {
if (!vis[i]) {
dfs(i);
subtreeSize[x]
+= subtreeSize[i];
}
}
}
// Function to print the
// required number of paths
void countPairs(int a, int b)
{
int sub = min(subtreeSize[a],
subtreeSize[b]);
cout << sub * (n - sub)
<< endl;
}
// Driver Code
int main()
{
// Number of vertices
n = 6;
addEdge(0, 1);
addEdge(0, 2);
addEdge(1, 3);
addEdge(3, 4);
addEdge(3, 5);
// Calling modified dfs function
dfs(0);
// Count pairs of vertices in the tree
countPairs(1, 3);
countPairs(0, 2);
return 0;
}
Java
// Java implementation for
// the above approach
import java.util.*;
class GFG{
static int sz = (int) 1e5;
// Adjacency list to
// represent the tree
static Vector []tree = new Vector[sz];
// Number of vertices
static int n;
// Mark visited/ unvisited
// vertices
static boolean []vis = new boolean[sz];
// Stores the subtree size
// of the corresponding nodes
static int []subtreeSize = new int[sz];
// Function to create an
// edge between two vertices
static void addEdge(int a, int b)
{
// Add a to b's list
tree[a].add(b);
// Add b to a's list
tree[b].add(a);
}
// Function to perform DFS
static void dfs(int x)
{
// Mark the vertex
// visited
vis[x] = true;
// Include the node in
// the subtree
subtreeSize[x] = 1;
// Traverse all its children
for (int i : tree[x])
{
if (!vis[i])
{
dfs(i);
subtreeSize[x] += subtreeSize[i];
}
}
}
// Function to print the
// required number of paths
static void countPairs(int a, int b)
{
int sub = Math.min(subtreeSize[a],
subtreeSize[b]);
System.out.print(sub * (n - sub) + "\n");
}
// Driver Code
public static void main(String[] args)
{
// Number of vertices
n = 6;
for (int i = 0; i < tree.length; i++)
tree[i] = new Vector();
addEdge(0, 1);
addEdge(0, 2);
addEdge(1, 3);
addEdge(3, 4);
addEdge(3, 5);
// Calling modified dfs function
dfs(0);
// Count pairs of vertices in the tree
countPairs(1, 3);
countPairs(0, 2);
}
}
// This code is contributed by 29AjayKumar
Python3
# Python3 implementation for
# the above approach
sz = 100000
# Adjacency list to
# represent the tree
tree = [[] for i in range(sz)]
# Number of vertices
n = 0
# Mark visited/ unvisited
# vertices
vis = [False] * sz
# Stores the subtree size
# of the corresponding nodes
subtreeSize = [0 for i in range(sz)]
# Function to create an
# edge between two vertices
def addEdge(a, b):
global tree
# Add a to b's list
tree[a].append(b)
# Add b to a's list
tree[b].append(a)
# Function to perform DFS
def dfs(x):
# Mark the vertex
# visited
global vis
global subtreeSize
global tree
vis[x] = True
# Include the node in
# the subtree
subtreeSize[x] = 1
# Traverse all its children
for i in tree[x]:
if (vis[i] == False):
dfs(i)
subtreeSize[x] += subtreeSize[i]
# Function to print the
# required number of paths
def countPairs(a, b):
global subtreeSize
sub = min(subtreeSize[a],
subtreeSize[b])
print(sub * (n - sub))
# Driver Code
if __name__ == '__main__':
# Number of vertices
n = 6
addEdge(0, 1)
addEdge(0, 2)
addEdge(1, 3)
addEdge(3, 4)
addEdge(3, 5)
# Calling modified dfs function
dfs(0)
# Count pairs of vertices in the tree
countPairs(1, 3)
countPairs(0, 2)
# This code is contributed by SURENDRA_GANGWAR
C#
// C# implementation for
// the above approach
using System;
using System.Collections.Generic;
class GFG{
static int sz = (int) 1e5;
// Adjacency list to
// represent the tree
static List []tree =
new List[sz];
// Number of vertices
static int n;
// Mark visited/ unvisited
// vertices
static bool []vis = new bool[sz];
// Stores the subtree size
// of the corresponding nodes
static int []subtreeSize = new int[sz];
// Function to create an
// edge between two vertices
static void addEdge(int a, int b)
{
// Add a to b's list
tree[a].Add(b);
// Add b to a's list
tree[b].Add(a);
}
// Function to perform DFS
static void dfs(int x)
{
// Mark the vertex
// visited
vis[x] = true;
// Include the node in
// the subtree
subtreeSize[x] = 1;
// Traverse all its children
foreach (int i in tree[x])
{
if (!vis[i])
{
dfs(i);
subtreeSize[x] += subtreeSize[i];
}
}
}
// Function to print the
// required number of paths
static void countPairs(int a, int b)
{
int sub = Math.Min(subtreeSize[a],
subtreeSize[b]);
Console.Write(sub * (n - sub) + "\n");
}
// Driver Code
public static void Main(String[] args)
{
// Number of vertices
n = 6;
for (int i = 0; i < tree.Length; i++)
tree[i] = new List();
addEdge(0, 1);
addEdge(0, 2);
addEdge(1, 3);
addEdge(3, 4);
addEdge(3, 5);
// Calling modified dfs function
dfs(0);
// Count pairs of vertices in the tree
countPairs(1, 3);
countPairs(0, 2);
}
}
// This code is contributed by 29AjayKumar
Javascript
9
5
时间复杂度: O(N + M + Q)
辅助空间: O(N)
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。