Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> C++

Thuật toán Fleury in đường đi/chu trình Euler trong C++

Thuật toán Fleury được dùng để hiển thị đường đi Euler hoặc chu trình Euler từ một đồ thị cho trước. Trong thuật toán này, bắt đầu từ một cạnh, nó cố gắng di chuyển đến các đỉnh kề khác bằng cách loại bỏ các đỉnh trước đó. Sử dụng thủ thuật này, đồ thị trở nên đơn giản hơn ở mỗi bước để tìm đường đi hoặc chu trình Euler.

Thuật toán Fleury in đường đi/chu trình Euler trong C++

Chúng ta cần kiểm tra một số quy tắc để lấy đường đi hoặc chu trình:

  • Đồ thị phải là đồ thị Euler.
  • Khi có hai cạnh, một là cầu (bridge), một không phải cầu, chúng ta phải chọn cạnh không phải cầu trước.

Việc chọn đỉnh bắt đầu cũng phức tạp: nếu đồ thị không có đỉnh bậc lẻ, ta có thể chọn bất kỳ đỉnh nào làm điểm bắt đầu; ngược lại nếu có đỉnh bậc lẻ, phải chọn đỉnh đó trước.

Đầu vào

Ma trận kề của đồ thị:

01111
10111
11011
11101
11110

Đầu ra

Đường đi hoặc Chu trình Euler: 1--0 0--2 2--1 1--3 3--0 0--4 4--3 3—2

Thuật toán

timDinhBatDau(dothi)
Đầu vào: Đồ thị cho trước. Đầu ra: Tìm đỉnh bắt đầu cho thuật toán.
Bắt đầu
    với mọi đỉnh i trong đồ thị, làm
        bac := 0
        với mọi đỉnh j kề với i, làm
            bac := bac + 1
        kết thúc
        nếu bac là lẻ, thì
            trả về i
        kết thúc nếu
    kết thúc vòng lặp
    khi tất cả bậc đều chẵn trả về 0
Kết thúc

laCau(u, v)
Đầu vào: Nút bắt đầu và nút kết thúc. Đầu ra: True khi u và v tạo thành cầu.
Bắt đầu
    bac := 0
    với mọi đỉnh i kề với v, làm
        bac := bac + 1
    kết thúc
    nếu bac > 1, thì
        trả về false
    trả về true
Kết thúc

fleuryAlgorithm(batdau)
Đầu vào: Đỉnh bắt đầu. Đầu ra: Hiển thị đường đi hoặc chu trình Euler.
Bắt đầu
    canh := lấy số cạnh trong đồ thị // không khởi tạo lại ở đệ quy sau
    với mọi đỉnh v kề với batdau, làm
        nếu canh <= 1 HOẶC laCau(batdau, v) là false, thì
            hiển thị đường đi từ batdau và v
            loại bỏ cạnh (batdau,v) khỏi đồ thị
            giảm canh đi 1
            fleuryAlgorithm(v)
        kết thúc nếu
    kết thúc vòng lặp
Kết thúc

Ví dụ mã C++

#include<iostream>
#include<vector>
#define NODE 5
using namespace std;

int graph[NODE][NODE] = {{0, 1, 1, 1, 1},
                         {1, 0, 1, 1, 0},
                         {1, 1, 0, 1, 0},
                         {1, 1, 1, 0, 1},
                         {1, 0, 0, 1, 0}};

int tempGraph[NODE][NODE];

int timDinhBatDau(){
    for(int i = 0; i<NODE; i++){
        int bac = 0;
        for(int j = 0; j<NODE; j++){
            if(tempGraph[i][j])
                bac++; // tăng bậc khi tìm thấy cạnh kết nối
        }
        if(bac % 2 != 0) // khi bậc của đỉnh là lẻ
            return i; // i là nút có bậc lẻ
    }
    return 0; // khi tất cả đỉnh đều có bậc chẵn, bắt đầu từ 0
}

bool laCau(int u, int v){
    int bac = 0;
    for(int i = 0; i<NODE; i++)
        if(tempGraph[v][i])
            bac++;
    if(bac>1){
        return false; // cạnh không tạo thành cầu
    }
    return true; // cạnh tạo thành cầu
}

int demCanh(){
    int count = 0;
    for(int i = 0; i<NODE; i++)
        for(int j = i; j<NODE; j++)
            if(tempGraph[i][j])
                count++;
    return count; // đếm số cạnh trong đồ thị
}

void fleuryAlgorithm(int batdau){
    static int canh = demCanh();
    for(int v = 0; v<NODE; v++){
        if(tempGraph[batdau][v]){ // khi cạnh (u,v) tồn tại và không tạo cầu
            if(canh <= 1 || !laCau(batdau, v)){
                cout << batdau << "--" << v << " ";
                tempGraph[batdau][v] = tempGraph[v][batdau] = 0; // loại bỏ cạnh khỏi đồ thị
                canh--; // giảm số cạnh
                fleuryAlgorithm(v);
            }
        }
    }
}

int main(){
    for(int i = 0; i<NODE; i++) // sao chép đồ thị chính sang tempGraph
        for(int j = 0; j<NODE; j++)
            tempGraph[i][j] = graph[i][j];
    cout << "Đường đi hoặc Chu trình Euler: ";
    fleuryAlgorithm(timDinhBatDau());
}

Kết quả đầu ra

Đường đi hoặc Chu trình Euler: 1--0 0--2 2--1 1--3 3--0 0--4 4--3 3—2