Skip to content
Related Articles

Related Articles

Improve Article
Save Article
Like Article

Shortest distance between given nodes in a bidirectional weighted graph by removing any K edges

  • Difficulty Level : Hard
  • Last Updated : 11 Oct, 2021

Given a positive integer K and a weighted undirected connected graph of N nodes and E edges as an array Edges[] of the type {u, v, W} representing the edges between Node u and Node v having weight W, the task is to find the shortest distance between the two given nodes S and D after reducing the cost of at most K edges to 0

Examples:

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.  To complete your preparation from learning a language to DS Algo and many more,  please refer Complete Interview Preparation Course.

In case you wish to attend live classes with experts, please refer DSA Live Classes for Working Professionals and Competitive Programming Live for Students.

Input: N = 5, K = 1, Edges[][] = {{0, 1, 1}, {0, 4, 1}, {1, 2, 2}, {2, 3, 4},  {4, 3, 7}}, s = 0, d = 3
Output: 1
Explanation:
Below is the graph for the given test case:



There are 2 possible routes between 0 and 3 viz. {0->1->2->3} and {0->4->3}
after reducing the distance of edge 4->3 to zero, the second route becomes 0->(4, 3) and hence the minimum distance is 1.

Input: N = 5, K = 2, Edges[][] = {{0, 1, 2}, {0, 2, 3}, {2, 1, 2}, {2, 3, 1}, {3, 1, 2}, {3, 4, 3}, {4, 2, 4}}, s = 0, d = 3
Ouput: 2

Approach: The given problem can be solved using DFS Traversal and storing all possible paths between the two given nodes. Follow the steps below to solve the given problem:

Below is the implementation of the above approach:

C++




// C++ program of the above approach
#include <bits/stdc++.h>
using namespace std;
  
// Function to get all the possible
// paths from the source to destination
void dfs_all(int n, int s, int d,
             vector<vector<pair<int, int> > >& graph,
             vector<bool>& vis,
             vector<vector<int> >& edge_path,
             vector<int>& temp_edge)
{
    // One possible path, reached node D
    if (s == d) {
        edge_path.push_back(temp_edge);
        return;
    }
  
    // Mark node s as visited
    vis[s] = true;
  
    // Calculate number of edges with
    // node s as connection
    int edges_in_a = graph[s].size();
  
    // Traverse all the connections
    // of node s
    for (int i = 0; i < edges_in_a; i++) {
  
        // If the connected node
        // isn't visited
        if (!vis[graph[s][i].first]) {
  
            // Push back edge value
            // in temp_edge
            temp_edge.push_back(
                graph[s][i].second);
  
            // Call DFS function recursively
            dfs_all(n, graph[s][i].first,
                    d, graph, vis,
                    edge_path, temp_edge);
  
            // Pop back last added edge
            temp_edge.pop_back();
        }
    }
  
    // Mark s as unvisited for more
    // possible paths
    vis[s] = false;
}
  
// Function to find the minimum sum of
// edges from source to destination
// after reducing at most K cost to 0
int getDistance(
    vector<vector<int> >& edge_path, int k)
{
    // Store the shortestDistance
    int shortestDistance = INT_MAX;
  
    // If edge_path vector is empty,
    // means no path exist
    if (edge_path.empty())
        return -1;
  
    // Traverse all the vector in
    // the edge_path
    for (auto x : edge_path) {
  
        // Base Case
        if (k == x.size())
            return 0;
  
        // lets sort the vector in
        // decreasing order
        sort(x.begin(), x.end(), greater<int>());
  
        // Find the sum of all the nodes
        int sum = 0;
  
        // Find the sum of k largest nodes
        int ksum = 0;
  
        for (int i = 0; i < x.size(); i++) {
            sum += x[i];
            if (i < k)
                ksum += x[i];
        }
  
        // If the given shortestDistance
        // is shortest, then update the
        // shortestDistance
        shortestDistance
            = min(sum - ksum, shortestDistance);
    }
  
    // Return the shortestDistance
    return shortestDistance;
}
  
// Function to find the minimum sum of
// weight of edges among all paths from
// source to destination after reducing
// at most K cost to 0
int solve(
    vector<vector<pair<int, int> > > graph,
    int n, int k, int src, int dest)
{
    // Stores all the vectors of edges for
    // every path traversed in DFS call
    vector<vector<int> > edge_path;
  
    // Store the edges of particular path
    vector<int> temp_edge;
  
    // Boolean visited vector
    vector<bool> vis(n, false);
  
    // DFS Call
    dfs_all(n, src, dest, graph,
            vis, edge_path, temp_edge);
  
    return getDistance(edge_path, k);
}
  
// Driver Code
int main()
{
    int n = 5, e = 5, k = 1;
    vector<vector<pair<int, int> > > graph(n);
  
    // Given Adjacency List
    graph[0].push_back(make_pair(1, 1));
    graph[1].push_back(make_pair(0, 1));
  
    graph[0].push_back(make_pair(4, 1));
    graph[4].push_back(make_pair(0, 1));
  
    graph[1].push_back(make_pair(2, 2));
    graph[2].push_back(make_pair(1, 2));
  
    graph[2].push_back(make_pair(3, 4));
    graph[3].push_back(make_pair(2, 4));
  
    graph[4].push_back(make_pair(3, 7));
    graph[3].push_back(make_pair(4, 7));
  
    int a = 0, b = 3;
  
    cout << solve(graph, n, k, a, b);
  
    return 0;
}
Output:
1

Time Complexity: O((N*log N)NN)
Auxiliary Space: O(N2)

Efficient Approach: The above approach can also be optimized at the step where sorting is performed after finding all possible paths. Instead of sorting, the idea is to use MinHeap to calculate the sum of K largest weights in the graph to reduce the time complexity to O(N*log K) for that steps.

Below is the implementation of the above approach:

C++




// C++ program of the above approach
#include <bits/stdc++.h>
using namespace std;
  
// Function to get all the possible
// paths from the source to destination
void dfs_all(int n, int s, int d,
             vector<vector<pair<int, int> > >& graph,
             vector<bool>& vis,
             vector<vector<int> >& edge_path,
             vector<int>& temp_edge)
{
    // One possible path, reached node D
    if (s == d) {
        edge_path.push_back(temp_edge);
        return;
    }
  
    // Mark node s as visited
    vis[s] = true;
  
    // Calculate number of edges with
    // node s as connection
    int edges_in_a = graph[s].size();
  
    // Traverse all the connections
    // of node s
    for (int i = 0; i < edges_in_a; i++) {
  
        // If the connected node
        // isn't visited
        if (!vis[graph[s][i].first]) {
  
            // Push back edge value
            // in temp_edge
            temp_edge.push_back(
                graph[s][i].second);
  
            // Call DFS function recursively
            dfs_all(n, graph[s][i].first,
                    d, graph, vis,
                    edge_path, temp_edge);
  
            // Pop back last added edge
            temp_edge.pop_back();
        }
    }
  
    // Mark s as unvisited for more
    // possible paths
    vis[s] = false;
}
  
// Function to find the minimum sum of
// edges from source to destination
// after reducing at most K cost to 0
int getDistance(
    vector<vector<int> >& edge_path, int k)
{
    int shortestDistance = INT_MAX;
  
    // If edge_path vector is empty,
    // means no path exist
    if (edge_path.empty())
        return -1;
  
    // Traverse all the vector in
    // the edge_path
    for (auto x : edge_path) {
  
        if (k == x.size())
            return 0;
  
        // Use heap to store the array
        priority_queue<int, vector<int>,
                       greater<int> >
            minHeap;
  
        // Find the sum of all the nodes
        int sum = 0;
  
        // Find the sum of k largest nodes
        int ksum = 0;
  
        // Find the largest K edges using
        // minHeap
        for (int i = 0; i < x.size(); i++) {
            sum += x[i];
            ksum += x[i];
  
            // Pushing edge in MinHeap
            minHeap.push(x[i]);
  
            // If heap size is K
            if (minHeap.size() > k) {
                ksum -= minHeap.top();
                minHeap.pop();
            }
        }
  
        // If the shortestDistance is
        // smallest, then update the
        // shortestDistance
        shortestDistance
            = min(sum - ksum, shortestDistance);
    }
  
    // Return the shortestDistance
    return shortestDistance;
}
  
// Function to find the minimum sum of
// weight of edges among all paths from
// source to destination after reducing
// at most K cost to 0
int solve(
    vector<vector<pair<int, int> > > graph,
    int n, int k, int src, int dest)
{
    // Stores all the vectors of edges for
    // every path traversed in DFS call
    vector<vector<int> > edge_path;
  
    // Store the edges of particular path
    vector<int> temp_edge;
  
    // Boolean visited vector
    vector<bool> vis(n, false);
  
    // DFS Call
    dfs_all(n, src, dest, graph,
            vis, edge_path, temp_edge);
  
    return getDistance(edge_path, k);
}
  
// Driver Code
int main()
{
    int n = 5, e = 5, k = 1;
    vector<vector<pair<int, int> > > graph(n);
  
    // Given Adjacency List
    graph[0].push_back(make_pair(1, 1));
    graph[1].push_back(make_pair(0, 1));
  
    graph[0].push_back(make_pair(4, 1));
    graph[4].push_back(make_pair(0, 1));
  
    graph[1].push_back(make_pair(2, 2));
    graph[2].push_back(make_pair(1, 2));
  
    graph[2].push_back(make_pair(3, 4));
    graph[3].push_back(make_pair(2, 4));
  
    graph[4].push_back(make_pair(3, 7));
    graph[3].push_back(make_pair(4, 7));
  
    int a = 0, b = 3;
  
    cout << solve(graph, n, k, a, b);
  
    return 0;
}
Output:
1

Time Complexity: O((N*log K)NN)
Auxiliary Space: O(N2)




My Personal Notes arrow_drop_up
Recommended Articles
Page :

Start Your Coding Journey Now!