📌  相关文章
📜  通过删除任何 K 条边,双向加权图中给定节点之间的最短距离

📅  最后修改于: 2022-05-13 01:56:09.900000             🧑  作者: Mango

通过删除任何 K 条边,双向加权图中给定节点之间的最短距离

给定一个正整数K和一个由N个节点和E个边组成的加权无向连通图,作为类型为 {u, v, W} 的数组Edges[] ,表示节点 u节点 v之间的边具有权重W ,任务是在将最多 K条边的成本减少到0后,找到两个给定节点SD之间的最短距离。

例子:

方法:给定问题可以使用 DFS 遍历并存储两个给定节点之间的所有可能路径来解决。请按照以下步骤解决给定的问题:

  • 初始化一个变量,比如minimumCostINT_MAX ,它存储了得到的最短距离。
  • 使用 DFS Traversal 遍历图中从节点S到节点D的所有路径,并将从节点SD获得的所有边权重存储在向量向量中,例如edgesPath[]
  • 完成上述步骤后,对存储在edgesPath[]中的每个向量进行降序排序。
  • 遍历每个向量的向量edgesPath[]的向量,比如A[] ,执行以下步骤:
    • A[]中前K个最大边的总和。
    • minimiumCost的值更新为当前(totalSum – sum)minimumCost的最小值。
  • 完成上述步骤后,打印minimumCost的值作为结果。

下面是上述方法的实现:

C++
// C++ program of the above approach
#include 
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 > >& graph,
             vector& vis,
             vector >& edge_path,
             vector& 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 >& 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());
  
        // 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 > > graph,
    int n, int k, int src, int dest)
{
    // Stores all the vectors of edges for
    // every path traversed in DFS call
    vector > edge_path;
  
    // Store the edges of particular path
    vector temp_edge;
  
    // Boolean visited vector
    vector 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 > > 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;
}


C++
// C++ program of the above approach
#include 
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 > >& graph,
             vector& vis,
             vector >& edge_path,
             vector& 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 >& 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,
                       greater >
            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 > > graph,
    int n, int k, int src, int dest)
{
    // Stores all the vectors of edges for
    // every path traversed in DFS call
    vector > edge_path;
  
    // Store the edges of particular path
    vector temp_edge;
  
    // Boolean visited vector
    vector 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 > > 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;
}


输出:
1

时间复杂度: O((N*log N)N N )
辅助空间: O(N 2 )

高效方法:上述方法也可以在找到所有可能路径后进行排序的步骤进行优化。这个想法不是排序,而是使用 MinHeap 计算图中K个最大权重的总和,以将这些步骤的时间复杂度降低到O(N*log K)

下面是上述方法的实现:

C++

// C++ program of the above approach
#include 
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 > >& graph,
             vector& vis,
             vector >& edge_path,
             vector& 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 >& 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,
                       greater >
            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 > > graph,
    int n, int k, int src, int dest)
{
    // Stores all the vectors of edges for
    // every path traversed in DFS call
    vector > edge_path;
  
    // Store the edges of particular path
    vector temp_edge;
  
    // Boolean visited vector
    vector 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 > > 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;
}
输出:
1

时间复杂度: O((N*log K)N N )
辅助空间: O(N 2 )