Johnson算法是一種用于解決有向圖最短路徑問題的算法。它的基本思想是通過對圖進行轉換,將原圖中的負權邊轉換為非負權邊,然后利用Dijkstra算法或Bellman-Ford算法求解最短路徑。
以下是使用C語言實現Johnson算法的基本步驟:
#define MAX_VERTEX 100
#define INF 9999
int graph[MAX_VERTEX][MAX_VERTEX];
void bellmanFord(int V, int start)
{
int dist[V];
for (int i = 0; i < V; i++)
dist[i] = INF;
dist[start] = 0;
for (int i = 0; i < V - 1; i++)
{
for (int u = 0; u < V; u++)
{
for (int v = 0; v < V; v++)
{
if (graph[u][v] != 0 && dist[u] + graph[u][v] < dist[v])
dist[v] = dist[u] + graph[u][v];
}
}
}
for (int u = 0; u < V; u++)
{
for (int v = 0; v < V; v++)
{
if (graph[u][v] != 0 && dist[u] + graph[u][v] < dist[v])
printf("圖中存在負權環,無法計算最短路徑");
}
}
// 將負權邊轉換為非負權邊
for (int u = 0; u < V; u++)
{
for (int v = 0; v < V; v++)
{
if (graph[u][v] != 0)
graph[u][v] += dist[u] - dist[v];
}
}
}
void dijkstra(int V, int start)
{
int dist[V];
bool visited[V];
for (int i = 0; i < V; i++)
{
dist[i] = INF;
visited[i] = false;
}
dist[start] = 0;
for (int count = 0; count < V - 1; count++)
{
int u = -1;
for (int i = 0; i < V; i++)
{
if (!visited[i] && (u == -1 || dist[i] < dist[u]))
u = i;
}
visited[u] = true;
for (int v = 0; v < V; v++)
{
if (!visited[v] && graph[u][v] != 0 && dist[u] != INF && dist[u] + graph[u][v] < dist[v])
dist[v] = dist[u] + graph[u][v];
}
}
printf("頂點 最短路徑\n");
for (int i = 0; i < V; i++)
{
if (dist[i] == INF)
printf("%d \t 無限遠\n", i);
else
printf("%d \t %d\n", i, dist[i]);
}
}
int main()
{
int V;
int start;
printf("輸入頂點數量:");
scanf("%d", &V);
printf("輸入起始頂點:");
scanf("%d", &start);
printf("輸入圖的鄰接矩陣:\n");
for (int i = 0; i < V; i++)
{
for (int j = 0; j < V; j++)
{
scanf("%d", &graph[i][j]);
}
}
bellmanFord(V, start);
dijkstra(V, start);
return 0;
}
上述代碼實現了Johnson算法,在輸入圖的鄰接矩陣后,根據起始頂點計算出圖中各頂點的最短路徑。