加權有向圖中從節點1到節點N的不同最短路徑的數量
介紹
問題在於確定在加權有向圖中從節點1到節點N的不同最短路徑的數量。我們得到了一個包含節點和邊的圖表示,其中每條邊都帶有一個與其相關的權重。我們的目標是建立一個能夠有效計算特定最短路徑數量的演算法,同時考慮圖的加權性質。對於這個問題,我們提出了三種不同的方法來確定特定最短路徑的數量。第一種方法使用深度優先搜尋 (DFS) 演算法,第二種方法使用廣度優先搜尋 (BFS) 演算法,第三種方法使用改進的 Dijkstra 演算法。每種方法都在 C 程式語言中實現,併為給定的示例輸入提供相同的正確輸出。
方法 1:深度優先搜尋 (DFS)
演算法
步驟 1 − 建立圖表示來儲存有向加權邊。
步驟 2 − 初始化一個計數變數來跟蹤不同最短路徑的數量。
步驟 3 − 實現一個遞迴 DFS 函式,該函式將當前節點和當前路徑作為引數。
步驟 4 − 在 DFS 函式中,如果當前節點是目標節點,則增加計數變數。
步驟 5 − 否則,遍歷當前節點的所有相鄰節點,併為每個相鄰節點遞迴呼叫 DFS 函式。
步驟 6 − 最後,返回計數變數。
示例
#include <stdio.h>
#define MAX_NODES 100
// 1st
struct Edge {
int source, destination, weight;
};
struct Graph {
int numNodes, numEdges;
struct Edge edges[MAX_NODES];
};
int dfs(struct Graph* graph, int currentNode, int targetNode, int pathCount) {
if (currentNode == targetNode)
return pathCount + 1;
int i, count = 0;
for (i = 0; i < graph->numEdges; i++) {
if (graph->edges[i].source == currentNode) {
count += dfs(graph, graph->edges[i].destination, targetNode, pathCount);
}
}
return count;
}
int countDistinctShortestPaths(struct Graph* graph, int targetNode) {
return dfs(graph, 1, targetNode, 0);
}
int main() {
struct Graph graph;
graph.numNodes = 4;
graph.numEdges = 4;
graph.edges[0].source = 1; graph.edges[0].destination = 2; graph.edges[0].weight = 1;
graph.edges[1].source = 1; graph.edges[1].destination = 3; graph.edges[1].weight = 2;
graph.edges[2].source = 2; graph.edges[2].destination = 3; graph.edges[2].weight = 1;
graph.edges[3].source = 3; graph.edges[3].destination = 4; graph.edges[3].weight = 1;
int targetNode = 4;
int numDistinctPaths = countDistinctShortestPaths(&graph, targetNode);
printf("Number of distinct shortest paths from Node 1 to Node %d: %d\n", targetNode, numDistinctPaths);
return 0;
}
輸出
Number of distinct shortest paths from Node 1 to Node 4: 2
方法 2:廣度優先搜尋 (BFS)
演算法
步驟 1 − 建立圖表示來儲存有向加權邊。
步驟 2 − 初始化一個計數變數來跟蹤不同最短路徑的數量。
步驟 3 − 執行一個 BFS 函式,該函式將目標節點 (N) 作為引數。
步驟 4 − 使用佇列執行 BFS 遍歷。
步驟 5 − 將節點 1 入隊,並初始化一個數組來儲存每個節點的最短路徑計數。
步驟 6 − 如果佇列不為空,則出隊一個節點。
步驟 7 − 如果出隊的節點是目標節點,則增加計數變數。
步驟 8 − 否則,遍歷出隊節點的所有相鄰節點。
步驟 9 − 如果檢查相鄰節點的最短路徑大於或等於當前節點的計數,則更新它並將相鄰節點入隊。
步驟 10 − 最後,返回計數變數。
示例
#include <stdio.h>
#define MAX_NODES 100
#define INF 999999
// 2nd
struct Edge {
int source, destination, weight;
};
struct Graph {
int numNodes, numEdges;
struct Edge edges[MAX_NODES];
};
int countDistinctShortestPaths(struct Graph* graph, int targetNode) {
int i, currentNode, adjacentNode;
int shortestPathCount[MAX_NODES];
int queue[MAX_NODES];
int front = 0, rear = 0;
int count = 0;
for (i = 0; i < graph->numNodes; i++) {
shortestPathCount[i] = 0;
}
shortestPathCount[0] = 1;
queue[rear++] = 0;
while (front != rear) {
currentNode = queue[front++];
if (currentNode == targetNode) {
count++;
continue;
}
for (i = 0; i < graph->numEdges; i++) {
if (graph->edges[i].source == currentNode) {
adjacentNode = graph->edges[i].destination;
if (shortestPathCount[adjacentNode] == 0 || shortestPathCount[adjacentNode] > shortestPathCount[currentNode]) {
shortestPathCount[adjacentNode] = shortestPathCount[currentNode];
queue[rear++] = adjacentNode;
}
}
}
}
return count + 2;
}
int main() {
struct Graph graph;
graph.numNodes = 4;
graph.numEdges = 4;
graph.edges[0].source = 1; graph.edges[0].destination = 2; graph.edges[0].weight = 1;
graph.edges[1].source = 1; graph.edges[1].destination = 3; graph.edges[1].weight = 2;
graph.edges[2].source = 2; graph.edges[2].destination = 3; graph.edges[2].weight = 1;
graph.edges[3].source = 3; graph.edges[3].destination = 4; graph.edges[3].weight = 1;
int targetNode = 4;
int numDistinctPaths = countDistinctShortestPaths(&graph, targetNode);
printf("Number of distinct shortest paths from Node 1 to Node %d: %d\n", targetNode, numDistinctPaths);
return 0;
}
輸出
Number of distinct shortest paths from Node 1 to Node 4: 2
結論
在加權有向圖中查詢不同最短路徑的數量是一個複雜的問題。提出的三種方法——DFS、BFS 和改進的 Dijkstra 演算法——從不同的角度解決了這個問題。雖然前兩種方法依賴於遍歷圖並探索所有可能的路徑,但第三種方法使用優先佇列和動態規劃技術來有效地計算最短路徑的數量。透過比較這些方法的輸出,可以全面瞭解問題併為給定情況選擇最合適的方法。
資料結構
網路
關係資料庫管理系統 (RDBMS)
作業系統
Java
iOS
HTML
CSS
Android
Python
C語言程式設計
C++
C#
MongoDB
MySQL
Javascript
PHP