Bellman-Ford單源最短路徑
阿新 • • 發佈:2018-12-22
Bellman-Ford演算法主要思想就是一個鬆弛
在有向圖中,在尋找的過程中找到的是隻能是當前的最小權重,但是當路徑向後推移的時候,可能就會有更小的權重出現了,那就換一條路(變化parent)給他鬆弛一下,得到更小的路徑。
最後那個布林值是在檢查是否存在一個可從源節點到達的權重為負值的環路,存在那麼這個圖就沒有解,否則就有解。
圖是這樣的,依舊是把字母按字母表的順序轉換成數字了。
程式碼
在圖演算法裡面,如果用矩陣來做,其實陣列還是挺好用的,這裡我都很少用結構體了,寫起來麻煩而且涉及到各種資料型別的不匹配。
#include "stdafx.h"
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define N 100
#define INF 0x3f3f3f3f
int map[N][N]; //儲存weight的二維陣列
int currentDistance[N] ; //結點當前的distance,過一會可能就變了。這是用於作比較的陣列
int parent[N] ; //這個陣列在我的程式裡實際上是沒用的,但是還是給他維護一下吧,這是正向的思維,尋找新的parent
int son[N] ; //這個陣列的功能是把路徑給輸出來,son陣列是parent陣列的逆陣列
int i, j,k;
int edgeNum; //邊的條數
int vertexNum; //結點的個數
bool BELLMAN_FORD(int s)
{
for (i = 0; i < N; i++) //初始化陣列
{
currentDistance[i] = INF;
parent[i] = -1;
son[i] = -1;
}
currentDistance[s] = 0;
for (k = 1; k < edgeNum; k++) //對每條邊進行V-1次處理
{
for (i = 0; i < N; i++) //鬆弛
for (j = 0; j < N; j++)
if (map[i][j] != INF)
{
if (currentDistance[j] > currentDistance[i] + map[i][j])
{
currentDistance[j] = currentDistance[i] + map[i][j];
parent[j] = i;
son[i] = j;
}
}
}
printf("%d,(%d)", s,currentDistance[s]);
for (i = 0; i < N; i++)
{
if (son[s] == i)
{
printf(" %d,(%d)", i, currentDistance[i]);
s = i;
i = 0;
}
}
for (i = 0; i < N; i++)
for (j = 0; j < N; j++)
{
if (map[i][j] != INF && currentDistance[j] > currentDistance[i] + map[i][j]) //是否存在權重為負值的環路並返回相應的布林值
return false;
else
return true;
}
}
int main() {
int s;
printf("輸入結點個數:\n");
scanf_s("%d", &vertexNum);
for (int i = 0; i < N; i++) //初始化矩陣為最大值
for (int j = 0; j < N; j++)
map[i][j] = INF;
printf("輸入邊的條數:\n");
scanf_s("%d", &edgeNum);
printf("輸入源結點:\n");
scanf_s("%d", &s);
printf("輸入兩點和權重(逗號分隔)\n");
int a, b, c;
for (int i = 0; i<edgeNum; i++) {
scanf_s("%d,%d,%d", &a, &b, &c);
map[a][b] = c; //注意無向圖在給矩陣賦值的時候是雙向的
}
printf("單源最短路徑:\n");
BELLMAN_FORD(s);
return 0;
}