Toán tin vuotlen.com

Thuật toán Floyd

 

Phân loại Thông tin
Tên thuật toán Floyd-Warshall (sử dụng cả ma trận kề và danh sách kề)
Phân loại thuật toán Thuật toán động (Dynamic Programming), thuật toán tìm đường đi ngắn nhất
Cấu trúc dữ liệu Ma trận kề hoặc Danh sách kề
Độ phức tạp thời gian (Worst Case) O(V³) với cả ma trận kề và danh sách kề
Độ phức tạp dung lượng O(V²) với ma trận kề
Độ phức tạp bộ nhớ O(V²) với ma trận kề
Phạm vi sử dụng Tìm đường đi ngắn nhất giữa mọi cặp đỉnh trong đồ thị có trọng số không âm hoặc âm
Khả năng xử lý trọng số âm Không
Khả năng xử lý chu trình âm Không
Người phát hiện đầu tiên Robert Floyd (1962), Stephen Warshall (1962)
Ứng dụng ban đầu Tìm đường đi ngắn nhất trong mạng lưới
Ứng dụng hiện đại Định tuyến mạng, phân phối mạng, tối ưu hóa, phát hiện vòng lặp trong đồ thị

 

Phân loại Thông tin
Ưu điểm - Tìm đường đi ngắn nhất giữa mọi cặp đỉnh trong đồ thị.
  - Linh hoạt với cả ma trận kề và danh sách kề.
  - Có thể xử lý đồ thị có trọng số âm, nhưng không thể có chu trình âm.
  - Đơn giản và dễ triển khai.
Nhược điểm - Độ phức tạp thời gian và bộ nhớ cao, không hiệu quả với đồ thị lớn.
  - Không thể xử lý chu trình âm.

Phạm vi sử dụng:

Ban đầu, thuật toán được sử dụng để tìm đường đi ngắn nhất giữa hai điểm trong một đồ thị có hướng. Tuy nhiên, sau này, thuật toán đã được mở rộng để tính toán đường đi ngắn nhất giữa tất cả các cặp đỉnh trong một đồ thị có hướng, cũng như trong đồ thị vô hướng.

Chi Tiết Kỹ Thuật Thuật Toán Floyd:

Pseudo-code của thuật toán Floyd:

function FloydWarshall(graph[][], V):
    // Khởi tạo ma trận khoảng cách
    dist[][] = new int[V][V]
    for i = 0 to V-1:
        for j = 0 to V-1:
            if i == j:
                dist[i][j] = 0  // Khoảng cách từ một đỉnh tới chính nó là 0
            else if graph[i][j] != 0:
                dist[i][j] = graph[i][j]  // Khởi tạo khoảng cách từ đỉnh i tới j bằng trọng số của cạnh (i, j)
            else:
                dist[i][j] = INF  // Khởi tạo khoảng cách từ đỉnh i tới j bằng vô cùng (không có cạnh nối trực tiếp)

    // Cập nhật khoảng cách trực tiếp và thông qua đỉnh trung gian
    for k = 0 to V-1:
        for i = 0 to V-1:
            for j = 0 to V-1:
                // Cập nhật khoảng cách từ i tới j thông qua đỉnh trung gian k
                if dist[i][k] + dist[k][j] < dist[i][j]:
                    dist[i][j] = dist[i][k] + dist[k][j]

    // Kiểm tra chu trình âm
    for i = 0 to V-1:
        if dist[i][i] < 0:
            return "Do thi co chu trinh am"

    // Trả về ma trận khoảng cách
    return dist

 

code C++:

#include <bits/stdc++.h>

 

using namespace std;

#define V 5
#define INF INT_MAX

// Khởi tạo ma trận trọng số ban đầu
void initializeDistanceMatrix(int dist[V][V], const int graph[V][V]) {
    for (int i = 0; i < V; ++i) {
        for (int j = 0; j < V; ++j) {
            if (i == j) {
                dist[i][j] = 0;
            } else if (graph[i][j] != 0) {
                dist[i][j] = graph[i][j];
            } else {
                dist[i][j] = INF;
            }
        }
    }
}

// Cập nhật ma trận trọng số
void updateDistanceMatrix(int dist[V][V], int k) {
    for (int i = 0; i < V; ++i) {
        for (int j = 0; j < V; ++j) {
            if (dist[i][k] != INF && dist[k][j] != INF && dist[i][k] + dist[k][j] < dist[i][j]) {
                dist[i][j] = dist[i][k] + dist[k][j];
            }
        }
    }
}

// Kiểm tra có chu trình âm hay không
bool hasNegativeCycle(const int dist[V][V]) {
    for (int i = 0; i < V; ++i) {
        if (dist[i][i] < 0) {
            return true;
        }
    }
    return false;
}

// In ma trận trọng số
void printDistanceMatrix(const int dist[V][V]) {
    cout << "Ma tran khoang cach ngan nhat giua cac cap dinh:\n";
    for (int i = 0; i < V; ++i) {
        for (int j = 0; j < V; ++j) {
            if (dist[i][j] == INF) {
                cout << "INF\t";
            } else {
                cout << dist[i][j] << "\t";
            }
        }
        cout << endl;
    }
}

// Thuật toán Floyd-Warshall
void floydWarshall(int graph[V][V]) {
    int dist[V][V];
    initializeDistanceMatrix(dist, graph);

    for (int k = 0; k < V; ++k) {
        updateDistanceMatrix(dist, k);
    }

    printDistanceMatrix(dist);

    if (hasNegativeCycle(dist)) {
        cout << "Do thi co chu trinh trong so am." << endl;
    }
}

int main() {
    // Ma trận kề đồ thị
    int graph[V][V] = {
        {0, 1, 0, 0, 5},
        {0, 0, 3, 3, 8},
        {0, 0, 0, 1, -5},
        {0, 0, 0, 0, 0},
        {0, 0, 0, 4, 0}
    };

    floydWarshall(graph);

    return 0;
}