多个未加权图上的 Dijkstra 最短路径?

Posted

技术标签:

【中文标题】多个未加权图上的 Dijkstra 最短路径?【英文标题】:Dijkstra shortest path on multiple unweighted graphs? 【发布时间】:2022-01-19 16:45:06 【问题描述】:

我正在试图弄清楚如何实现 djiktra 算法来找到 2 个未加权图之间的最短路径。我得到的建议是使用 2 个图,一个用于红色,一个用于蓝色。旅行的成本始终为 1,但要在蓝色时访问红色方块,您需要支付 2 来切换图形

我主要是在寻找建议和参考有没有人做过类似的事情???

【问题讨论】:

您应该添加一些代码,到目前为止您尝试了什么? 您仍然可以将其建模为一张图。红红边的权重为 1,红蓝边的权重为 3(正常行程为 1,切换颜色为 2) 不是未加权图。成本是 1 或 2(或者是 1 还是 3,问题没有说清楚)。这应该是应用此成本值的标准 Dijkstra 算法。 _我得到的建议是使用 2 个图表 _ 我建议忽略这个建议。它应该被建模为一个加权图。 【参考方案1】:

基于原始图创建一个新的加权图,其中蓝色 -> 红色路径花费 3 而不是 1,然后在其上运行 Dijkstra。

编辑:可能没有必要实际创建新图,您可以直接从原始图获取权重,但首先创建新图可能更容易理解。

顶角如下所示:

A ← 3 → B ← 1 → C ← 1 → D ...
↑       ↑       ↑
1       1       3  
↓       ↓       ↓
E ← 3 → F ← 3 → G...

【讨论】:

问题是,如果我通过支付 2 将颜色变为蓝色,我不应该每次在蓝色瓷砖上行走时都必须继续支付 3 是的,只调整改变颜色的边缘的成本 所以我需要在每次颜色变化时不断更改图形权重? 我为您的原始图表的左上角添加了一个示例,希望它更清晰 好吧,你的意思是,只有红色和蓝色连接在一起,成本才应该是 3,否则就是 1【参考方案2】:

要创建图形,请使用此伪代码在节点之间添加边

AddEdge( n1, n2 )
SET cost = 1
IF n1color != n2color
   SET cost = 3;
graph.AddEdge( n1, n2, cost );
RUN Dijsktra on graph

【讨论】:

【参考方案3】:

这只是标准的 Dijkstra。

这不是未加权的图,您需要从一个顶点移动到另一个顶点。从一种颜色切换到另一种颜色只是一个额外的规则,需要额外的费用。

您所需要的只是一个计算两个顶点之间成本的函数,该函数只需查看每个顶点的颜色并适当地增加成本。请参阅:int getCost(Graph const& graph, Point src, Point dst) 下方。

除此之外,它是您应该应用的标准算法。


// Not pure C++
// But left enough work that you have to make an effort
// to complete this.

enum Color  Red, Blue;
using Graph = std::vector_like<std::vector_like<Color>>;
using Point = std::pair<int, int>;

int getCost(Graph const& graph, Point src, Point dst)

    // Assumes: src and dst are 1 point away from each other.
    //          This assumes that work is done via
    //          getListOfPointsReachable() which only gets nodes
    //          nodes that are adjecent.
    //          
    // Standard movement cost.
    int cost = 1;

    // Add a cost if switching between blue red.
    if (graph[src] !=  graph[dst]) 
        cost += 2;
    
    return cost;


std::list<Point> getListOfPointsReachable(Graph const& graph, Point src)

    // Get a list of points that can be accessed by src.
    // All points that are next to the current and return as a list.
    // Check if they are out of bounds.


void Dijkstra(Graph const& graph, Point start, Point end)

    std::set<Point>  visited;

    // Boundary:  int   => Cost
    //            Point => Point cost applies to.
    // Using tuple as it already has the comparison operator defined.
    using Boundary = std::tuple<int, Point>;
    std:: priority_queue<Boundary>   boundary;

    // Set up the boundary list with a start.
    boundary.emplace(0, start);

    while (!boundary.empty())
    
        Boundary next = boundry.top();
        boundary.pop();

        int      cost = std::get<0>(next);
        Point    nextP = std::get<1>(next);

        if (nextP == end)
        
            throw std::runtime_error("Found route to end: Cheapest Route is: " + cost);
        
        if (visited.find(nextP) != std::end(visited))
        
            // we already did this node.
            continue;
        
        visited.insert(nextP);

        std::list<Point> dests = getListOfPointsReachable(graph, nextP);
        for (auto const& dest: dests)
        
            int extraCost = getCost(graph, nextP, dest);
            boundary.emplace(extraCost + cost, dest);
        
    
    throw std::runtime_error("No Route from Start to End");
 

【讨论】:

以上是关于多个未加权图上的 Dijkstra 最短路径?的主要内容,如果未能解决你的问题,请参考以下文章

图上权重变化的最短路径

日日算法:Dijkstra算法

单源最短路径---Dijkstra算法

在非加权图中找到最短路径

图最短路径?

图的最短路径的Dijkstra算法及Floyd算法