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

📅  最后修改于: 2021-05-06 10:27:03             🧑  作者: 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


输出:
9
5









时间复杂度: O(N + M + Q)
辅助空间: O(N)