穿过m条边的最短路径

问题描述

你好,有聪明的人。

我有以下图形问题。

给出具有n个顶点的完整的,有向的,加权的图,找到经过m-1条边(路径中的边可能重复)的最短路径(从任何顶点开始)的长度。 至于限制n

看看极限,我可以说必须有某种巧妙的方法来进行某种dp和图遍历,但是我只是想不到类似的东西。 预先感谢。

Example:
n = 3,m = 5

edges:
1 -> 2 weight = 10,1 -> 3 weight = 100,2 -> 1 weight = 10,2 -> 3 weight = 50,3 -> 1 weight = 30,3 -> 2 weight = 70,answer would be 40 (1 -> 2 -> 1 -> 2 -> 1)

解决方法

天真的解决方案是运行BFS(宽度优先搜索)直到第m 级别,并保持最小的权重总和并返回。


但是在问题中,它说我们可以多次包含顶点,直到它们之间有路径为止,所以现在我们可以执行以下步骤:

  1. 计算图中显示的所有周期,我们可以在计算最小重量时重用这些周期。

例如:

在这个问题中,存在一个循环1-->2-->1,长度为3权重= 20,m的值为5,现在我们可以使用该路径两次,但是如果m为6,则剩下还有1个节点。


  1. 现在我们可以从l计算长度为1(如果m = 6,则为1)的最小路径(包括剩余节点)并将其添加到上述权重中。 (我们将1-> 2 = 10)

  1. 为图形中出现的每个循环重复步骤1和2 ,并保持最小和。

下面是描述上述解决方案的c ++代码(虽然可能不是100%正确,但是您将了解基本思想)

#include <iostream>
#include <queue>
#include <vector>

using namespace std;

struct Edge{
    int src,dest,weight;
};

struct Node{
    int start_vertex,end_vertex,weight,edge_count=0;
};

class Graph{
public: 
    vector<vector<pair<int,int>>> adjList;
    int V;

    Graph(vector<Edge> edges,int V){

        adjList.resize(V+1);
        this->V = V;

        for(Edge edge:edges){
            adjList[edge.src].push_back({edge.dest,edge.weight});
        }
    }
};

int BFS(Graph &g,int m){

    queue<Node> Q;

    vector<Node> cycles;

    // to store min path from vertex i of length j
    vector<vector<int>> dp(g.V+1,vector<int>(g.V+1,INT_MAX));

    for(int i=0; i<=g.V; i++)
        dp[i][0] = 0;

    for(int i=1; i<=g.V; i++){
        Q.push({i,i,1});
    }

    while(!Q.empty()){
        Node top = Q.front();

        Q.pop();

        if(top.edge_count >= g.V) break;

        int v = top.end_vertex;
        int start_vertex = top.start_vertex;
        int weight = top.weight;
        int edge_count = top.edge_count;

        for(auto x:g.adjList[v]){
            // finding all the cycles
            if(x.first == start_vertex){
                Node n = {start_vertex,v,weight+x.second,edge_count+1};
                cycles.push_back(n);
            }else{
                Q.push({start_vertex,x.first,edge_count+1});
            }


            if(dp[start_vertex][edge_count] > weight+x.second){
                dp[start_vertex][edge_count] = weight+x.second;
            }
        }
    }

    // finding minimum:
    int min_weight = INT_MAX;

    if(m<=g.V){
        for(int i=1; i<=g.V; i++){
            min_weight = min(min_weight,dp[i][m]);
        }
    }

    // checking all the cycles for  reusability and maintaining min sum
    for(int i=0; i<cycles.size(); i++){

        int sum = cycles[i].weight;

        int length_left_to_cover = m-cycles[i].edge_count;

        sum += length_left_to_cover/(cycles[i].edge_count-1) * cycles[i].weight;

        int vertices_left_to_include = 0;

        if(m-cycles[i].edge_count>0){

            vertices_left_to_include = (m-cycles[i].edge_count)%(cycles[i].edge_count-1);

        }

        min_weight = min(min_weight,sum+dp[cycles[i].start_vertex][vertices_left_to_include]);
    }

    return min_weight;


}

// 1 -> 2 weight = 10,// 1 -> 3 weight = 100,// 2 -> 1 weight = 10,// 2 -> 3 weight = 50,// 3 -> 1 weight = 30,// 3 -> 2 weight = 70,int main(){
    vector<Edge> edges = {
        {1,2,10},{1,3,100},{2,1,50},{3,30},70}
    };

    int V = 3;
    int m = 5;

    Graph g(edges,V);

    cout<<"Min weight: "<<BFS(g,m);
}

输出:

Min weight: 40

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...