📜  一棵树中所有最短路径的总和

📅  最后修改于: 2021-04-29 01:30:35             🧑  作者: Mango

给定一个加权无向图T ,该图T[0,N – 1]个节点和类型为{ uvw }的Edges [] [3]数组组成,表示顶点uv之间具有权重w的边。任务是找到给定树中所有最短路径对的总和。

例子:

天真的方法:最简单的方法是使用Floyd Warshall算法在每对顶点之间找到最短路径。在预先计算每对节点之间最短路径的成本之后,请打印所有最短路径的总和。

下面是上述方法的实现:

C++
// C++ program for the above approach
 
#include 
using namespace std;
#define INF 99999
 
// Function that performs the Floyd
// Warshall to find all shortest paths
int floyd_warshall(int* graph, int V)
{
 
    int dist[V][V], i, j, k;
 
    // Initialize the distance matrix
    for (i = 0; i < V; i++) {
        for (j = 0; j < V; j++) {
            dist[i][j] = *((graph + i * V) + j);
        }
    }
 
    for (k = 0; k < V; k++) {
 
        // Pick all vertices as
        // source one by one
        for (i = 0; i < V; i++) {
 
            // Pick all vertices as
            // destination for the
            // above picked source
            for (j = 0; j < V; j++) {
 
                // If vertex k is on the
                // shortest path from i to
                // j then update dist[i][j]
                if (dist[i][k]
                        + dist[k][j]
                    < dist[i][j]) {
                    dist[i][j]
                        = dist[i][k]
                          + dist[k][j];
                }
            }
        }
    }
 
    // Sum the upper diagonal of the
    // shortest distance matrix
    int sum = 0;
 
    // Traverse the given dist[][]
    for (i = 0; i < V; i++) {
 
        for (j = i + 1; j < V; j++) {
 
            // Add the distance
            sum += dist[i][j];
        }
    }
 
    // Return the final sum
    return sum;
}
 
// Function to generate the tree
int sumOfshortestPath(int N, int E,
                      int edges[][3])
{
    int g[N][N];
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++) {
            g[i][j] = INF;
        }
    }
 
    // Add edges
    for (int i = 0; i < E; i++) {
 
        // Get source and destination
        // with weight
        int u = edges[i][0];
        int v = edges[i][1];
        int w = edges[i][2];
 
        // Add the edges
        g[u][v] = w;
        g[v][u] = w;
    }
 
    // Perform Floyd Warshal Algorithm
    return floyd_warshall((int*)g, N);
}
 
// Driver code
int main()
{
    // Number of Vertices
    int N = 4;
 
    // Number of Edges
    int E = 3;
 
    // Given Edges with weight
    int Edges[][3]
        = { { 0, 1, 1 }, { 1, 2, 2 },
            { 2, 3, 3 } };
 
    // Function Call
    cout << sumOfshortestPath(N, E, Edges);
 
    return 0;
}


Java
// Java program for
// the above approach
class GFG{
   
static final int INF = 99999;
 
// Function that performs the Floyd
// Warshall to find all shortest paths
static int floyd_warshall(int[][] graph,
                          int V)
{
  int [][]dist = new int[V][V];
  int i, j, k;
 
  // Initialize the distance matrix
  for (i = 0; i < V; i++)
  {
    for (j = 0; j < V; j++)
    {
      dist[i][j] = graph[i][j];
    }
  }
 
  for (k = 0; k < V; k++)
  {
    // Pick all vertices as
    // source one by one
    for (i = 0; i < V; i++)
    {
      // Pick all vertices as
      // destination for the
      // above picked source
      for (j = 0; j < V; j++)
      {
        // If vertex k is on the
        // shortest path from i to
        // j then update dist[i][j]
        if (dist[i][k] + dist[k][j] <
            dist[i][j])
        {
          dist[i][j] = dist[i][k] +
                       dist[k][j];
        }
      }
    }
  }
 
  // Sum the upper diagonal of the
  // shortest distance matrix
  int sum = 0;
 
  // Traverse the given dist[][]
  for (i = 0; i < V; i++)
  {
    for (j = i + 1; j < V; j++)
    {
      // Add the distance
      sum += dist[i][j];
    }
  }
 
  // Return the final sum
  return sum;
}
 
// Function to generate the tree
static int sumOfshortestPath(int N, int E,
                             int edges[][])
{
  int [][]g = new int[N][N];
  for (int i = 0; i < N; i++)
  {
    for (int j = 0; j < N; j++)
    {
      g[i][j] = INF;
    }
  }
 
  // Add edges
  for (int i = 0; i < E; i++)
  {
    // Get source and destination
    // with weight
    int u = edges[i][0];
    int v = edges[i][1];
    int w = edges[i][2];
 
    // Add the edges
    g[u][v] = w;
    g[v][u] = w;
  }
 
  // Perform Floyd Warshal Algorithm
  return floyd_warshall(g, N);
}
 
// Driver code
public static void main(String[] args)
{
  // Number of Vertices
  int N = 4;
 
  // Number of Edges
  int E = 3;
 
  // Given Edges with weight
  int Edges[][] = {{0, 1, 1}, {1, 2, 2},
                   {2, 3, 3}};
 
  // Function Call
  System.out.print(
         sumOfshortestPath(N, E, Edges));
}
}
 
// This code is contributed by 29AjayKumar


Python3
# Python3 program for the above approach
INF = 99999
 
# Function that performs the Floyd
# Warshall to find all shortest paths
def floyd_warshall(graph, V):
 
    dist = [[0 for i in range(V)]
               for i in range(V)]
 
    # Initialize the distance matrix
    for i in range(V):
        for j in range(V):
            dist[i][j] = graph[i][j]
 
    for k in range(V):
         
        # Pick all vertices as
        # source one by one
        for i in range(V):
             
            # Pick all vertices as
            # destination for the
            # above picked source
            for j in range(V):
                 
                # If vertex k is on the
                # shortest path from i to
                # j then update dist[i][j]
                if (dist[i][k] + dist[k][j] < dist[i][j]):
                    dist[i][j] = dist[i][k] + dist[k][j]
 
    # Sum the upper diagonal of the
    # shortest distance matrix
    sum = 0
 
    # Traverse the given dist[][]
    for i in range(V):
        for j in range(i + 1, V):
             
            # Add the distance
            sum += dist[i][j]
 
    # Return the final sum
    return sum
 
# Function to generate the tree
def sumOfshortestPath(N, E,edges):
     
    g = [[INF for i in range(N)]
              for i in range(N)]
               
    # Add edges
    for i in range(E):
         
        # Get source and destination
        # with weight
        u = edges[i][0]
        v = edges[i][1]
        w = edges[i][2]
 
        # Add the edges
        g[u][v] = w
        g[v][u] = w
 
    # Perform Floyd Warshal Algorithm
    return floyd_warshall(g, N)
 
# Driver code
if __name__ == '__main__':
     
    # Number of Vertices
    N = 4
 
    # Number of Edges
    E = 3
 
    # Given Edges with weight
    Edges = [ [ 0, 1, 1 ],
              [ 1, 2, 2 ],
              [ 2, 3, 3 ] ]
 
    # Function Call
    print(sumOfshortestPath(N, E, Edges))
 
# This code is contributed by mohit kumar 29


C#
// C# program for
// the above approach
using System;
class GFG{
   
static readonly int INF = 99999;
 
// Function that performs the Floyd
// Warshall to find all shortest paths
static int floyd_warshall(int[,] graph,
                          int V)
{
  int [,]dist = new int[V, V];
  int i, j, k;
 
  // Initialize the distance matrix
  for (i = 0; i < V; i++)
  {
    for (j = 0; j < V; j++)
    {
      dist[i, j] = graph[i, j];
    }
  }
 
  for (k = 0; k < V; k++)
  {
    // Pick all vertices as
    // source one by one
    for (i = 0; i < V; i++)
    {
      // Pick all vertices as
      // destination for the
      // above picked source
      for (j = 0; j < V; j++)
      {
        // If vertex k is on the
        // shortest path from i to
        // j then update dist[i,j]
        if (dist[i, k] + dist[k, j] <
            dist[i, j])
        {
          dist[i, j] = dist[i, k] +
                       dist[k, j];
        }
      }
    }
  }
 
  // Sum the upper diagonal of the
  // shortest distance matrix
  int sum = 0;
 
  // Traverse the given dist[,]
  for (i = 0; i < V; i++)
  {
    for (j = i + 1; j < V; j++)
    {
      // Add the distance
      sum += dist[i, j];
    }
  }
 
  // Return the readonly sum
  return sum;
}
 
// Function to generate the tree
static int sumOfshortestPath(int N, int E,
                             int [,]edges)
{
  int [,]g = new int[N, N];
   
  for (int i = 0; i < N; i++)
  {
    for (int j = 0; j < N; j++)
    {
      g[i, j] = INF;
    }
  }
 
  // Add edges
  for (int i = 0; i < E; i++)
  {
    // Get source and destination
    // with weight
    int u = edges[i, 0];
    int v = edges[i, 1];
    int w = edges[i, 2];
 
    // Add the edges
    g[u, v] = w;
    g[v, u] = w;
  }
 
  // Perform Floyd Warshal Algorithm
  return floyd_warshall(g, N);
}
 
// Driver code
public static void Main(String[] args)
{
  // Number of Vertices
  int N = 4;
 
  // Number of Edges
  int E = 3;
 
  // Given Edges with weight
  int [,]Edges = {{0, 1, 1},
                  {1, 2, 2},
                  {2, 3, 3}};
 
  // Function Call
  Console.Write(sumOfshortestPath(N,
                                  E, Edges));
}
}
 
// This code is contributed by 29AjayKumar


C++
// C++ program for the above approach
#include
using namespace std;
 
// Function that performs the DFS
// traversal to find cost to reach
// from vertex v to other vertexes
void dfs(int v, int p,
         vector> t[],
         int h, int ans[])
{
     
    // Traverse the Adjacency list
    // of u
    for(pair u : t[v])
    {
        if (u.first == p)
            continue;
             
        // Recursive Call
        dfs(u.first, v, t, h + u.second, ans);
    }
     
    // Update ans[v]
    ans[v] = h;
}
 
// Function to find the sum of
// weights of all paths
int solve(int n, int edges[][3])
{
     
    // Stores the Adjacency List
    vector> t[n];
 
    // Store the edges
    for(int i = 0; i < n - 1; i++)
    {
        t[edges[i][0]].push_back({edges[i][1],
                                  edges[i][2]});
 
        t[edges[i][1]].push_back({edges[i][0],
                                  edges[i][2]});
    }
 
    // sum is the answer
    int sum = 0;
 
    // Calculate sum for each vertex
    for(int i = 0; i < n; i++)
    {
        int ans[n];
         
        // Perform the DFS Traversal
        dfs(i, -1, t, 0, ans);
 
        // Sum of distance
        for(int j = 0; j < n; j++)
            sum += ans[j];
    }
     
    // Return the final sum
    return sum / 2;
}
 
// Driver Code
int main()
{
     
    // No of vertices
    int N = 4;
 
    // Given Edges
    int edges[][3] = { { 0, 1, 1 },
                       { 1, 2, 2 },
                       { 2, 3, 3 } };
 
    // Function Call
    cout << solve(N, edges) << endl;
     
    return 0;
}
 
// This code is contributed by pratham76


Java
// Java program for the above approach
 
import java.io.*;
import java.awt.*;
import java.io.*;
import java.util.*;
 
@SuppressWarnings("unchecked")
class GFG {
 
    // Function that performs the DFS
    // traversal to find cost to reach
    // from vertex v to other vertexes
    static void dfs(int v, int p,
                    ArrayList t[],
                    int h, int ans[])
    {
 
        // Traverse the Adjacency list
        // of u
        for (Point u : t[v]) {
            if (u.x == p)
                continue;
 
            // Recursive Call
            dfs(u.x, v, t, h + u.y, ans);
        }
 
        // Update ans[v]
        ans[v] = h;
    }
 
    // Function to find the sum of
    // weights of all paths
    static int solve(int n, int edges[][])
    {
 
        // Stores the Adjacency List
        ArrayList t[]
            = new ArrayList[n];
 
        for (int i = 0; i < n; i++)
            t[i] = new ArrayList<>();
 
        // Store the edges
        for (int i = 0; i < n - 1; i++) {
 
            t[edges[i][0]].add(
                new Point(edges[i][1],
                          edges[i][2]));
 
            t[edges[i][1]].add(
                new Point(edges[i][0],
                          edges[i][2]));
        }
 
        // sum is the answer
        int sum = 0;
 
        // Calculate sum for each vertex
        for (int i = 0; i < n; i++) {
 
            int ans[] = new int[n];
 
            // Perform the DFS Traversal
            dfs(i, -1, t, 0, ans);
 
            // Sum of distance
            for (int j = 0; j < n; j++)
                sum += ans[j];
        }
 
        // Return the final sum
        return sum / 2;
    }
 
    // Driver Code
    public static void main(String[] args)
    {
        // No of vertices
        int N = 4;
 
        // Given Edges
        int edges[][]
            = new int[][] { { 0, 1, 1 },
                            { 1, 2, 2 },
                            { 2, 3, 3 } };
 
        // Function Call
        System.out.println(solve(N, edges));
    }
}


Python3
# Python3 program for the above approach
 
# Function that performs the DFS
# traversal to find cost to reach
# from vertex v to other vertexes
def dfs(v, p, t, h, ans):
 
    # Traverse the Adjacency list
    # of u
    for u in t[v]:
        if (u[0] == p):
            continue
         
        # Recursive Call
        dfs(u[0], v, t, h + u[1], ans)
 
    # Update ans[v]
    ans[v] = h
 
# Function to find the sum of
# weights of all paths
def solve(n, edges):
  
    # Stores the Adjacency List
    t = [[] for i in range(n)]
     
    # Store the edges
    for i in range(n - 1):
        t[edges[i][0]].append([edges[i][1],
                               edges[i][2]])
        t[edges[i][1]].append([edges[i][0],
                               edges[i][2]])
 
    # sum is the answer
    sum = 0
  
    # Calculate sum for each vertex
    for i in range(n):
        ans = [0 for i in range(n)]
  
        # Perform the DFS Traversal
        dfs(i, -1, t, 0, ans)
  
        # Sum of distance
        for j in range(n):
            sum += ans[j]
  
    # Return the final sum
    return sum // 2
     
# Driver Code
if __name__ == "__main__":
    
    # No of vertices
    N = 4
  
    # Given Edges
    edges = [ [ 0, 1, 1 ],
              [ 1, 2, 2 ],
              [ 2, 3, 3 ] ]
  
    # Function Call
    print(solve(N, edges))
 
# This code is contributed by rutvik_56


C#
// C# program for the above approach
using System;
using System.Collections.Generic;
 
class GFG{
 
// Function that performs the DFS
// traversal to find cost to reach
// from vertex v to other vertexes
static void dfs(int v, int p,
                List> []t,
                int h, int []ans)
{
     
    // Traverse the Adjacency list
    // of u
    foreach(Tuple u in t[v])
    {
        if (u.Item1 == p)
            continue;
 
        // Recursive call
        dfs(u.Item1, v, t,
        h + u.Item2, ans);
    }
 
    // Update ans[v]
    ans[v] = h;
}
 
// Function to find the sum of
// weights of all paths
static int solve(int n, int [,]edges)
{
     
    // Stores the Adjacency List
    List> []t = new List>[n];
 
    for(int i = 0; i < n; i++)
        t[i] = new List>();
 
    // Store the edges
    for(int i = 0; i < n - 1; i++)
    {
        t[edges[i, 0]].Add(
            new Tuple(edges[i, 1],
                                edges[i, 2]));
 
        t[edges[i, 1]].Add(
            new Tuple(edges[i, 0],
                                edges[i, 2]));
    }
 
    // sum is the answer
    int sum = 0;
 
    // Calculate sum for each vertex
    for(int i = 0; i < n; i++)
    {
        int []ans = new int[n];
 
        // Perform the DFS Traversal
        dfs(i, -1, t, 0, ans);
 
        // Sum of distance
        for(int j = 0; j < n; j++)
            sum += ans[j];
    }
 
    // Return the readonly sum
    return sum / 2;
}
 
// Driver Code
public static void Main(String[] args)
{
     
    // No of vertices
    int N = 4;
 
    // Given Edges
    int [,]edges = new int[,] { { 0, 1, 1 },
                                { 1, 2, 2 },
                                { 2, 3, 3 } };
 
    // Function call
    Console.WriteLine(solve(N, edges));
}
}
 
// This code is contributed by Amit Katiyar


输出:
20

时间复杂度: O(N 3 ),其中N是顶点数。
辅助空间: O(N)

高效的方法:想法是使用DFS算法,使用DFS,对于每个顶点,可以在线性时间内找到从该顶点访问每个其他顶点的成本。请按照以下步骤解决问题:

  1. 遍历节点0N – 1
  2. 对于每个节点i ,使用源为节点i的DFS查找访问其他每个顶点的成本之和,并用S i表示该总和。
  3. 现在,计算S = S 0 + S 1 +…+ S N-1 。将S除以2,因为每个路径都计算两次。
  4. 完成上述步骤后,打印获得的总和S的值。

下面是上述方法的实现:

C++

// C++ program for the above approach
#include
using namespace std;
 
// Function that performs the DFS
// traversal to find cost to reach
// from vertex v to other vertexes
void dfs(int v, int p,
         vector> t[],
         int h, int ans[])
{
     
    // Traverse the Adjacency list
    // of u
    for(pair u : t[v])
    {
        if (u.first == p)
            continue;
             
        // Recursive Call
        dfs(u.first, v, t, h + u.second, ans);
    }
     
    // Update ans[v]
    ans[v] = h;
}
 
// Function to find the sum of
// weights of all paths
int solve(int n, int edges[][3])
{
     
    // Stores the Adjacency List
    vector> t[n];
 
    // Store the edges
    for(int i = 0; i < n - 1; i++)
    {
        t[edges[i][0]].push_back({edges[i][1],
                                  edges[i][2]});
 
        t[edges[i][1]].push_back({edges[i][0],
                                  edges[i][2]});
    }
 
    // sum is the answer
    int sum = 0;
 
    // Calculate sum for each vertex
    for(int i = 0; i < n; i++)
    {
        int ans[n];
         
        // Perform the DFS Traversal
        dfs(i, -1, t, 0, ans);
 
        // Sum of distance
        for(int j = 0; j < n; j++)
            sum += ans[j];
    }
     
    // Return the final sum
    return sum / 2;
}
 
// Driver Code
int main()
{
     
    // No of vertices
    int N = 4;
 
    // Given Edges
    int edges[][3] = { { 0, 1, 1 },
                       { 1, 2, 2 },
                       { 2, 3, 3 } };
 
    // Function Call
    cout << solve(N, edges) << endl;
     
    return 0;
}
 
// This code is contributed by pratham76

Java

// Java program for the above approach
 
import java.io.*;
import java.awt.*;
import java.io.*;
import java.util.*;
 
@SuppressWarnings("unchecked")
class GFG {
 
    // Function that performs the DFS
    // traversal to find cost to reach
    // from vertex v to other vertexes
    static void dfs(int v, int p,
                    ArrayList t[],
                    int h, int ans[])
    {
 
        // Traverse the Adjacency list
        // of u
        for (Point u : t[v]) {
            if (u.x == p)
                continue;
 
            // Recursive Call
            dfs(u.x, v, t, h + u.y, ans);
        }
 
        // Update ans[v]
        ans[v] = h;
    }
 
    // Function to find the sum of
    // weights of all paths
    static int solve(int n, int edges[][])
    {
 
        // Stores the Adjacency List
        ArrayList t[]
            = new ArrayList[n];
 
        for (int i = 0; i < n; i++)
            t[i] = new ArrayList<>();
 
        // Store the edges
        for (int i = 0; i < n - 1; i++) {
 
            t[edges[i][0]].add(
                new Point(edges[i][1],
                          edges[i][2]));
 
            t[edges[i][1]].add(
                new Point(edges[i][0],
                          edges[i][2]));
        }
 
        // sum is the answer
        int sum = 0;
 
        // Calculate sum for each vertex
        for (int i = 0; i < n; i++) {
 
            int ans[] = new int[n];
 
            // Perform the DFS Traversal
            dfs(i, -1, t, 0, ans);
 
            // Sum of distance
            for (int j = 0; j < n; j++)
                sum += ans[j];
        }
 
        // Return the final sum
        return sum / 2;
    }
 
    // Driver Code
    public static void main(String[] args)
    {
        // No of vertices
        int N = 4;
 
        // Given Edges
        int edges[][]
            = new int[][] { { 0, 1, 1 },
                            { 1, 2, 2 },
                            { 2, 3, 3 } };
 
        // Function Call
        System.out.println(solve(N, edges));
    }
}

Python3

# Python3 program for the above approach
 
# Function that performs the DFS
# traversal to find cost to reach
# from vertex v to other vertexes
def dfs(v, p, t, h, ans):
 
    # Traverse the Adjacency list
    # of u
    for u in t[v]:
        if (u[0] == p):
            continue
         
        # Recursive Call
        dfs(u[0], v, t, h + u[1], ans)
 
    # Update ans[v]
    ans[v] = h
 
# Function to find the sum of
# weights of all paths
def solve(n, edges):
  
    # Stores the Adjacency List
    t = [[] for i in range(n)]
     
    # Store the edges
    for i in range(n - 1):
        t[edges[i][0]].append([edges[i][1],
                               edges[i][2]])
        t[edges[i][1]].append([edges[i][0],
                               edges[i][2]])
 
    # sum is the answer
    sum = 0
  
    # Calculate sum for each vertex
    for i in range(n):
        ans = [0 for i in range(n)]
  
        # Perform the DFS Traversal
        dfs(i, -1, t, 0, ans)
  
        # Sum of distance
        for j in range(n):
            sum += ans[j]
  
    # Return the final sum
    return sum // 2
     
# Driver Code
if __name__ == "__main__":
    
    # No of vertices
    N = 4
  
    # Given Edges
    edges = [ [ 0, 1, 1 ],
              [ 1, 2, 2 ],
              [ 2, 3, 3 ] ]
  
    # Function Call
    print(solve(N, edges))
 
# This code is contributed by rutvik_56

C#

// C# program for the above approach
using System;
using System.Collections.Generic;
 
class GFG{
 
// Function that performs the DFS
// traversal to find cost to reach
// from vertex v to other vertexes
static void dfs(int v, int p,
                List> []t,
                int h, int []ans)
{
     
    // Traverse the Adjacency list
    // of u
    foreach(Tuple u in t[v])
    {
        if (u.Item1 == p)
            continue;
 
        // Recursive call
        dfs(u.Item1, v, t,
        h + u.Item2, ans);
    }
 
    // Update ans[v]
    ans[v] = h;
}
 
// Function to find the sum of
// weights of all paths
static int solve(int n, int [,]edges)
{
     
    // Stores the Adjacency List
    List> []t = new List>[n];
 
    for(int i = 0; i < n; i++)
        t[i] = new List>();
 
    // Store the edges
    for(int i = 0; i < n - 1; i++)
    {
        t[edges[i, 0]].Add(
            new Tuple(edges[i, 1],
                                edges[i, 2]));
 
        t[edges[i, 1]].Add(
            new Tuple(edges[i, 0],
                                edges[i, 2]));
    }
 
    // sum is the answer
    int sum = 0;
 
    // Calculate sum for each vertex
    for(int i = 0; i < n; i++)
    {
        int []ans = new int[n];
 
        // Perform the DFS Traversal
        dfs(i, -1, t, 0, ans);
 
        // Sum of distance
        for(int j = 0; j < n; j++)
            sum += ans[j];
    }
 
    // Return the readonly sum
    return sum / 2;
}
 
// Driver Code
public static void Main(String[] args)
{
     
    // No of vertices
    int N = 4;
 
    // Given Edges
    int [,]edges = new int[,] { { 0, 1, 1 },
                                { 1, 2, 2 },
                                { 2, 3, 3 } };
 
    // Function call
    Console.WriteLine(solve(N, edges));
}
}
 
// This code is contributed by Amit Katiyar
输出:
20

时间复杂度: O(N 2 ),其中N是顶点数。
辅助空间: O(N)