📜  在包含给定边的树中查找最短路径数的查询

📅  最后修改于: 2021-10-27 07:52:01             🧑  作者: Mango

给定一棵树,它有N个顶点,编号从0N – 1,有 M 条边, Q查询的形式为{U, V},这样树中UV之间就有一条直接边。每个查询的任务是从包含给定节点对之间的边的给定树中的任何可能的无序顶点对之间找到所有可能的最短路径。

例子:

方法:该问题可以基于以下观察来解决:对于任何查询{U, V},如果其中一个节点位于树中,则树中任何一对节点之间的最短路径将包含给定边(U, V) U 的子树,另一个节点位于剩余的树中。因此,所需的对数为:

因此,请按照以下步骤解决问题:

  • 从根节点开始对树执行深度优先搜索遍历。
  • 对于每个节点,将节点数存储在其子树中(包括节点)。
  • 迭代每个查询 (U, 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 现场工作专业课程学生竞争性编程现场课程