首頁  >  文章  >  後端開發  >  在一個有向加權圖中,求解恰好包含k條邊的最短路徑

在一個有向加權圖中,求解恰好包含k條邊的最短路徑

PHPz
PHPz轉載
2023-09-11 19:17:02989瀏覽

在一個有向加權圖中,求解恰好包含k條邊的最短路徑

在協調加權圖表中,找到具有精確 k 個邊的最簡短路徑的問題包括確定在精確導航 k 個邊時權重最小的路徑。這將透過採用動態程式設計策略來實現,例如採用 3D 框架來儲存所有可想到的方式中的最小權重。計算在頂點和邊上重複,在每一步都調整最小權重。透過考慮具有精確 k 個邊的所有可能的方式,計算可以區分圖表中具有 k 個邊的最有限的方式。

使用的方法

  • 樸素遞迴方法

  • 具有邊緣約束的 Dijkstra 演算法

樸素遞歸方法

樸素遞歸方法可能是解決問題的一種重要而明確的策略,包括將複雜的問題分解為更小的子問題並遞歸地解決它們。在這種方法中,作品多次調用自身來探討子問題,直到達到基本情況。儘管如此,由於重複計算和覆蓋子問題,對於更大的問題發生可能會造成浪費。它需要諸如記憶或能量編程之類的最佳化方法。容易受騙的遞歸方法很容易取得和實現,但可能會承受指數時間複雜度。它通常用於解決小規模問題或作為更優化計算的起點。

演算法

  • 表徵工作最短路徑(圖、u、v、k),路徑以圖表、來源頂點 u、目標頂點 v 和邊數 k 作為輸入。

  • 檢查基本情況:

  • #a。如果 k 和 u 與 v 收支平衡,則返回(因為在這種情況下不允許有邊)。

  • 第二個。如果 k 為 1 且圖表中 u 和 v 之間存在邊,則傳回其權重。

  • c.如果 k 小於或等於 0,則傳回無邊界(因為不允許負邊緣或零邊緣)。

  • 初始化一個無限的變數res來儲存最短路徑距離。

  • 圖表應如下迭代所有頂點:

  • a。如果 u 和 i 沒有上升到 u 或 v,則從 u 到 i 存在一邊:

  • 遞迴呼叫shortestPath,其中i為現代源頂點,v為目標頂點,k−1為剩餘邊數。

  • 如果傳回的結果不是無限的,則將res升級為res和目前邊的權重與遞歸結果的最小值。

  • 傳回 res 的值,作為精確分離 k 個邊的最有限方式。

範例

#include <iostream>
#include <climits>

#define V 4
#define INF INT_MAX

int shortestPathWithKEdges(int graph[][V], int source, int destination, int k) {
    // Base cases
    if (k == 0 && source == destination)
        return 0;
    if (k == 1 && graph[source][destination] != INF)
        return graph[source][destination];
    if (k <= 0)
        return INF;

    // Initialize result
    int shortestPathDistance = INF;

    // Explore all adjacent vertices of the source vertex
    for (int i = 0; i < V; i++) {
        if (graph[source][i] != INF && source != i && destination != i) {
            int recursiveDistance = shortestPathWithKEdges(graph, i, destination, k - 1);
            if (recursiveDistance != INF)
                shortestPathDistance = std::min(shortestPathDistance, graph[source][i] + recursiveDistance);
        }
    }

    return shortestPathDistance;
}

int main() {
    int graph[V][V] = {
        {0, 10, 3, 2},
        {INF, 0, INF, 7},
        {INF, INF, 0, 6},
        {INF, INF, INF, 0}
    };
    int source = 0, destination = 3, k = 2;
    std::cout << "Weight of the shortest path is " << shortestPathWithKEdges(graph, source, destination, k) << std::endl;
    return 0;
}

輸出

Weight of the shortest path is 9

帶有邊緣約束的 Dijkstra 演算法

帶邊限制的 Dijkstra 演算法是一種圖表遍歷計算,用於識別圖表上來源頂點與所有其他頂點之間的最短路徑。它考慮了圖表邊緣的限製或約束,例如最極端或最不極端的邊緣權重。此計算保留所需的頂點線並迭代地選擇移除最少的頂點。此時,如果找到較短的路徑,它會透過增加相鄰頂點的間距來放鬆它們。此準備工作將持續進行,直到訪問完所有頂點為止。具有邊緣命令的 Dijkstra 演算法保證所選擇的方式滿足所需的邊緣限制,同時找到最有限的方式

演算法

  • 使用以下參數製作 Dijkstra 的作品

  • #Graph:有頂點和邊的輸入圖表

    來源:最有限路徑的起始頂點

    約束:邊緣的限製或障礙

    初始化一組已消失的頂點和一條用於儲存頂點及其距離的需求線。

  • 建立一個刪除簇,並將除來源頂點之外的所有頂點的刪除設定為可終止性,來源頂點設為 0。

  • 將來源頂點以其距離排列到所需的行中。

  • 雖然需求管線無法清除,但請執行下列操作:

  • 將消除次數最少的頂點從所需佇列中出列。

  • 如果現在不再造訪該頂點,

  • 將其標記為已存取。

  • 對於現代頂點的每個相鄰頂點:

  • 應用邊緣障礙來決定是否可以考慮邊緣。

  • 考慮邊緣權重和約束,計算從供給頂點到相鄰頂點的未使用距離。

  • 如果目前的分隔符號比現代的分隔符號短,請改進分隔符號數組。

  • 將相鄰頂點以其未使用的距離排隊到所需的行中。

  • 到達所有頂點後,單獨的叢集將包含從供應頂點到滿足邊緣限制的每個頂點的最大短距離。

  • 傳回單獨的簇作為結果。

示例

#include <iostream>
#include <vector>
#include <limits>

struct Edge {
    int destination;
    int weight;
};

void dijkstra(const std::vector<std::vector<Edge>>& graph, int source, std::vector<int>& distance) {
    int numVertices = graph.size();
    std::vector<bool> visited(numVertices, false);
    distance.resize(numVertices, std::numeric_limits<int>::max());
    distance[source] = 0;

    for (int i = 0; i < numVertices - 1; ++i) {
        int minDistance = std::numeric_limits<int>::max();
        int minVertex = -1;

        for (int v = 0; v < numVertices; ++v) {
            if (!visited[v] && distance[v] < minDistance) {
                minDistance = distance[v];
                minVertex = v;
            }
        }

        if (minVertex == -1)
            break;

        visited[minVertex] = true;

        for (const auto& edge : graph[minVertex]) {
            int destination = edge.destination;
            int weight = edge.weight;

            if (!visited[destination] && distance[minVertex] != std::numeric_limits<int>::max() &&
                distance[minVertex] + weight < distance[destination]) {
                distance[destination] = distance[minVertex] + weight;
            }
        }
    }
}

int main() {
    int numVertices = 4;
    int source = 0;
    std::vector<std::vector<Edge>> graph(numVertices);

    // Add edges to the graph (destination, weight)
    graph[0] = {{1, 10}, {2, 3}};
    graph[1] = {{2, 1}, {3, 7}};
    graph[2] = {{3, 6}};

    std::vector<int> distance;
    dijkstra(graph, source, distance);

    // Print the shortest distances from the source vertex
    std::cout << "Shortest distances from vertex " << source << ":\n";
    for (int i = 0; i < numVertices; ++i) {
        std::cout << "Vertex " << i << ": " << distance[i] << '\n';
    }

    return 0;
}

输出

Shortest distances from vertex 0:
Vertex 0: 0
Vertex 1: 10
Vertex 2: 3
Vertex 3: 9

结论

本文概述了两个重要的计算,以帮助理解协调和加权图表中的大多数问题。它阐明了易受骗的递归方法和带有边缘限制的 Dijkstra 计算。轻信递归方法包括递归地研究具有精确 k 个边的所有可能的方式,以发现最有限的方式。 Dijkstra 的边命令式计算采用了所需的线和面积规则,成功地找出了图表中从供给顶点到所有不同顶点的最大受限方式。本文包含了计算的具体说明,并给出了测试代码来说明其用法.

以上是在一個有向加權圖中,求解恰好包含k條邊的最短路徑的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:tutorialspoint.com。如有侵權,請聯絡admin@php.cn刪除