1. 程式人生 > >程式設計基礎26 弗洛伊德演算法

程式設計基礎26 弗洛伊德演算法

題目描述

在帶權有向圖G中,求G中的任意一對頂點間的最短路徑問題,也是十分常見的一種問題。

解決這個問題的一個方法是執行n次迪傑斯特拉演算法,這樣就可以求出每一對頂點間的最短路徑,執行的時間複雜度為O(n3)。

而另一種演算法是由弗洛伊德提出的,時間複雜度同樣是O(n3),但演算法的形式簡單很多。

可以將弗洛伊德演算法描述如下:

在本題中,讀入一個有向圖的帶權鄰接矩陣(即陣列表示),建立有向圖並按照以上描述中的演算法求出每一對頂點間的最短路徑長度。

 

輸入

輸入的第一行包含1個正整數n,表示圖中共有n個頂點。其中n不超過50。

以後的n行中每行有n個用空格隔開的整數。對於第i行的第j個整數,如果大於0,則表示第i個頂點有指向第j個頂點的有向邊,且權值為對應的整數值;如果這個整數為0,則表示沒有i指向j的有向邊。當i和j相等的時候,保證對應的整數為0。

輸出

共有n行,每行有n個整數,表示源點至每一個頂點的最短路徑長度。如果不存在從源點至相應頂點的路徑,輸出-1。對於某個頂點到其本身的最短路徑長度,輸出0。

請在每個整數後輸出一個空格,並請注意行尾輸出換行。

樣例輸入

4
0 3 0 1
0 0 4 0
2 0 0 0
0 0 1 0

樣例輸出

0 3 2 1 
6 0 4 7 
2 5 0 3 
3 6 1 0 

一,注意事項

    初始化是把不能達到的距離初始化成INF,因為Floyed()子函式中有一項是dis[i][k]+dis[k][j]<dis[i][j],dis[i][j]是無窮大的話只要有中介點使其連通便可輕易替換。

    還有就是把橫縱座標相等的點初始化為0,

    關於本題還有一項,就是輸出的時候若是兩點不可達要用-1來替換!當初就是在這WA的。

二,我的程式碼

#include<cstdio>
#include<algorithm>
using namespace std;
const int INF = 1000000000;
const int max_n = 60;
int N = 0;
int dis[max_n][max_n];
using namespace std;
void Floyed() {
	for (int i = 1; i <= N; i++) {
		for (int j = 1; j <= N; j++) {
			if (dis[i][j] == 0) {
				dis[i][j] = INF;
			}
		}
	}
	for (int i = 1; i <= N; i++) {
		dis[i][i] = 0;
	}
	for (int k = 1; k <= N; k++) {
		for (int i = 1; i <= N; i++) {
			for (int j = 1; j <= N; j++) {
				if (dis[i][k] != INF && dis[k][j] != INF && dis[i][k] + dis[k][j] < dis[i][j]) {
					dis[i][j] = dis[i][k] + dis[k][j];
				}
			}
		}
	}
	for (int i = 1; i <= N; i++) {
		for (int j = 1; j <= N; j++) {
			if (dis[i][j] == INF) {
				dis[i][j] = -1;
			}
		}
	}
}
int main() {
	scanf("%d", &N);
	for (int i = 1; i <= N; i++) {
		for (int j = 1; j <= N; j++) {
			scanf("%d", &dis[i][j]);
		}
	}
	Floyed();
	for (int i = 1; i <= N; i++) {
		for (int j = 1; j <= N; j++) {
			printf("%d", dis[i][j]);
			if (j != N) {
				printf(" ");
			}
		}
		printf("\n");
	}
	return 0;
}