Sum of all Pair Shortest Paths in a Tree


The term "sum of all pair shortest paths" in a tree refers to calculating the total of all node pairs' individual shortest paths. An effective way to do this is to use the Double DFS (Depth-First Search) algorithm. Determine the separation between a chosen node and every other node during the first DFS pass. Once more traverse the tree during the second DFS pass, taking into account each node as a potential LCA (Lowest Common Ancestor), and add up the distances between pairs of nodes that are descendants of the chosen LCA. The sum of all pair shortest paths in a tree can be calculated using this method with the assurance of an ideal solution.

Methods Used

  • Double DFS (Depth-First Search) Approach

  • Dynamic Programming Approach

Double DFS (Depth-First Search) Approach

For the total of all pair shortest paths in a tree, we use the Double DFS (Depth-First Search) approach, which involves two DFS passes. To begin, we compute the distances to all other nodes starting from any node. Then, during the second DFS pass, we navigate the tree while considering each node as a potential LCA. We compute and sum the distances between pairs of nodes that are offspring of the selected LCA while traversing. We obtain the total sum of all pair shortest paths by repeating this process for all nodes. This strategy is exceptionally compelling for this issue since it productively calculates the sum of distances between all sets of nodes in a tree.

Algorithm

  • Any node within the tree can serve as the beginning node.

  • To determine the distances of all other nodes from the chosen beginning node, perform a Depth-First Search (DFS) beginning from that node. These separations ought to be spared in an array or information structure.

  • Next, run a second DFS on the tree, treating each node as a possible LCA (Lowest Common Ancestor).

  • Calculate the distances between pairs of nodes that are descendants of the chosen LCA while traversing the tree during the second DFS. For each LCA, add these distances together.

  • Repeat this procedure for every node in the tree.

  • The whole sum of all matches in the most limited ways within the tree is represented by the sum of all calculated distances from step 4.

Example

#include <iostream>
#include <vector>
using namespace std;

const int MAXN = 10005;
vector<int> graph[MAXN];
int ancestor[MAXN];

int dfs(int node, int lca, int distance) {
   int sum = 0;
   for (int neighbor : graph[node]) {
      if (neighbor != lca) {
         sum += dfs(neighbor, lca, distance + 1);
      }
   }
   return sum + distance;
}

int main() {

   int lca_node = 0;
   int total_sum = 0;

   for (int node = 0; node < MAXN; ++node) {
      if (node != lca_node) {
         total_sum += dfs(node, lca_node, 0);
      }
   }

   cout << "Total sum of distances between descendants of the LCA: " << total_sum << endl;

   return 0;
}

Output

Total sum of distances between descendants of the LCA: 0

Dynamic Programming Approach:

We begin by choosing any node as the root and transform the tree into a rooted tree in the Dynamic Programming approach for the sum of all pair shortest paths in a tree. We calculate the partition between each node and the root utilising dynamic programming, and at that point we store the results in an array. After that, for each node, we add up the separations of its children from the root (already computed) to determine the whole separations for all other nodes. In this way, we are able to rapidly calculate the overall number of pairwise shortest paths. As a proficient solution to the issue, the algorithm includes a time complexity of O(N), where N is the number of nodes within the tree.

Algorithm

  • Make any node in the tree the root and root the tree (for example, using a deep search of the root node) to create a rooted tree.

  • Dynamic programming can be used to determine how far each node is from the root. Those distances should be stored in an array or data structure.

  • Calculate the entirety of the distances from each node within the tree to all other nodes:

  • a. Move through the current node's children.

    b. To account for paths that pass through the current node, add the number of nodes in each child's subtree and the distance to the root that was previously calculated for each child.

    c. Add up these amounts for every child of the active node.

    d. To the final result, add the total for the current node.

  • The total sum of all pair shortest paths in the tree is the final result.

#include <iostream>
#include <vector>

using namespace std;

struct TreeNode {
   int val;
   vector<TreeNode*> children;
};

int dfs(TreeNode* node, vector<int>& distances) {
   int subtree_size = 1;
   for (TreeNode* child : node->children) {
      subtree_size += dfs(child, distances);
      distances[node->val] += distances[child->val] + subtree_size;
   }
   return subtree_size;
}

int sumOfAllPairShortestPaths(TreeNode* root) {
   vector<int> distances(root->val + 1, 0);
   dfs(root, distances);
   int total_sum = 0;
   for (int distance : distances) {
      total_sum += distance;
   }
   return total_sum;
}

int main() {
   TreeNode* root = new TreeNode{0};
   int result = sumOfAllPairShortestPaths(root);
   cout << "Sum of all pair shortest paths in the tree: " << result << endl;
   return 0;
}

Output

Sum of all pair shortest paths in the tree: 0

Conclusion

The sum of all pair shortest paths in a tree can be calculated using the Double DFS (Depth-First Search) approach or dynamic programming. The Double DFS approach consists of two passes, where we first compute the distances from a selected node to all other nodes, and then we traverse the tree again while considering each node as a potential Lowest Common Ancestor (LCA), to add up distances between pairs of descendant nodes. The Dynamic Programming approach entails recursively using DFS to root the tree and calculate distances from the root to every other node. The results of both approaches are identical and consist of the sum of all pairwise shortest paths in the tree.The decision between the two algorithms may be based on particular implementation preferences or tree structures, but both algorithms offer effective solutions.

Updated on: 04-Aug-2023

247 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements