Thuật toán ghép cặp của Edmonds

Thuật toán ghép cặp của Edmonds (còn gọi là thuật toán bông hoa) là một thuật toán trong lý thuyết đồ thị để tìm cặp ghép cực đại trong đồ thị. Thuật toán được tìm ra bởi Jack Edmonds năm 1961, và xuất bản năm 1965. Cho trước một đồ thị vô hướng "G" = ("V", "E"), thuật toán tìm ra cặp ghép "M" sao cho mỗi đỉnh trong "V" kề với tối đa một cạnh trong "M" và |"M"| là lớn nhất có thể. Cặp ghép được xây dựng bằng cách khởi đầu từ cặp ghép rỗng và tăng dần lên bằng các đường tăng. Không như cặp ghép cho đồ thị hai phía, ý tưởng mới quan trọng nhất ở đây là có thể thu gọn một chu trình lẻ (bông hoa) thành một đỉnh, và việc tìm kiếm được thực hiện trên đồ thị đã thu gọn.

Thuật toán này là chứng minh đầu tiên cho việc có thể tìm cặp ghép cực đại trong thời gian đa thức. Một đóng góp quan trọng nữa là nó giúp mô tả đa diện quy hoạch tuyến tính của bài toán cặp ghép, từ đó xây dựng thuật toán tìm cặp ghép "trọng số" nhỏ nhất. 
Theo Alexander Schrijver, một điểm nổi bật nữa là đa diện này là đa diện đầu tiên được chứng minh là nguyên "không suy ra trực tiếp từ đơn môđula hoàn toàn, và mô tả của nó là một bước đột phá trong tổ hợp đa diện."

==Đường tăng==
Xét đồ thị "G" = ("V", "E") và cặp ghép "M" của "G". Đỉnh "v" là tự do, nếu không có cạnh nào của "M" kề với "v". Một đường trong "G" là một đường luân phiên, nếu các cạnh của nó luân phiên nhau không nằm trong "M" và nằm trong "M" (hoặc trong "M" và không trong "M"). Một đường tăng "P" là một đường luân phiên bắt đầu và kết thúc ở hai đỉnh tự do. Một phép tăng cặp ghép dọc theo đường tăng "P" là việc thay "M" bằng cặp ghép formula_1.

Có thể chứng minh cặp ghép "M" là cực đại khi và chỉ khi không tồn tại đường tăng cho "M" trong "G". Do đó, hoặc một cặp ghép là cực đại, hoặc tồn tại đường tăng cho nó. Vì vậy, xuất phát từ một cặp ghép ban đầu (có thể rỗng), có thể tìm cặp ghép cực đại bằng cách tăng cặp ghép dọc theo đường tăng chừng nào còn tồn tại đường tăng, và trả về cặp ghép cuối cùng khi không tồn tại đường tăng nào. Có thể tóm tắt thuật toán như sau:

Một điểm chưa rõ trong mô tả trên là cách tìm đường tăng một cách hiệu quả. Việc tìm đường tăng sẽ sử dụng khái niệm bông hoa và thu gọn hoa.

==Bông hoa và thu gọn hoa==
Xét đồ thị "G" = ("V", "E") và cặp ghép "M" của "G". Một "bông hoa" "B" là một chu trình trong "G" gồm "2k + 1" cạnh trong đó đúng "k" cạnh nằm trong "M", và có một đỉnh "v" của chu trình ("đế hoa") sao cho tồn tại một đường luân phiên độ dài chẵn ("cuống hoa") từ "v" đến một đỉnh tự do "w".

Định nghĩa đồ thị thu gọn "G’" là đồ thị thu được từ "G" bằng cách thu gọn toàn bộ "B" vào đỉnh đế hoa, và định nghĩa cặp ghép thu gọn "M’" là cặp ghép trong "G’" tương ứng với "M".

Có thể chứng minh rằng "G’" có đường tăng cho "M’" khi và chỉ khi "G" có đường tăng cho "M" và mỗi đường tăng "P’" cho "M’" trong "G’" có thể được nâng lên thành một đường tăng cho "M" trong "G" bằng cách đảo ngược thao tác thu gọn "B" sao cho nếu "P’" đi qua đỉnh đế hoa "v" thì mở rộng nó bằng một đường tương ứng trong "B". Cụ thể hơn:

- nếu "P’" đi qua hai cạnh "u → v → w" trong "G’", thì mở rộng đoạn đường này thành "u → (u’ →... → w’) → w" trong "G", trong đó "u’" và "w’" là hai đỉnh của hoa và trong hai nửa của "B" đi từ "u’" đến "w’", chọn nửa duy trì tính luân phiên của đường đi.

Như vậy có thể thu gọn các bông hoa và việc tìm đường tăng có thể được thực hiện trên đồ thị thu gọn. Thao tác này là ý tưởng chủ đạo của thuật toán Edmonds.

==Tìm đường tăng==
Việc tìm đường tăng sử dụng một cấu trúc dữ liệu hỗ trợ để lưu trữ một rừng "F" trong đó mỗi cây ứng với một phần của đồ thị "G" mà thuật toán đã tìm ra đường luân phiên từ đỉnh gốc của cây tới các đỉnh còn lại trong cây. Rừng "F" giống như rừng được dùng trong việc tìm cặp ghép trên đồ thị hai phía (ngoại trừ việc thu gọn bông hoa).

Thuật toán gán nhãn cho các đỉnh "v" của đồ thị. Nhãn gồm hai phần: đỉnh gốc của cây chứa "v", và tính chẵn lẻ của độ dài đường luân phiên từ gốc của cây chứa "v" đến "v".

Thuật toán lần lượt xem xét các đỉnh "v" và cạnh "e" của "G" và thay đổi"F" một cách thích hợp. Nếu "v" nằm trong một cây "T" trong rừng "F", đặt "gốc(v)" là đỉnh gốc của "T". Nếu cả "u" và "v" nằm trong cùng một cây "T" trong "F", đặt "khoảng_cách(u,v)" là chiều dài đường đi duy nhất từ "u" đến "v" trên cây "T".