LỜI MỞ ĐẦU Bài toán luồng cực đại trong mạng cũng là một trong số những bài toán tối ưu trên đồ thị tìm được những ứng dụng rộng rãi trong thực tế.. Bài toán luồng cực đại trong mạng có
Trang 1ĐẠI HỌC ĐÀ NẴNG ĐẠI HỌC BÁCH KHOA KHOA CÔNG NGHỆ THÔNG TIN
ĐỒ ÁN
GIẢI THUẬT & LẬP TRÌNH
Đề tài : Tìm luồng cực đại trên mạng
GVHD : NGUYỄN VĂN HIỆU SVTH : VÕ ĐỨC HÙNG SƠN – MAI VĂN TUẤN LỚP : 16T3
NHÓM : 16N11E
Đà Nẵng 12-2018
Trang 2LỜI MỞ ĐẦU
Bài toán luồng cực đại trong mạng cũng là một trong số những bài toán tối ưu trên
đồ thị tìm được những ứng dụng rộng rãi trong thực tế Bài toán được đề xuất vào đầu
những năm 1950 [1], và gắn liền với tên tuổi của hai nhà bác học Mỹ là L.R.Ford và D.R.Fulkerson Bài toán luồng cực đại trong mạng có nhiều ứng dụng trong thực tế như:
Bài toán xác định cường độ dòng lớn nhất của dòng vận tải giữa hai nút của một bản đồ giao thông, bài toán tìm luồng dầu lớn nhất có thể bơm từ tàu chở dầu vào bể chứa của một hệ thống đường ống dẫn dầu…Ngoài ra, ứng dụng của bài toán còn để giải các bài toán như: bài toán phân nhóm sinh hoạt, bài toán lập lịch cho hội nghị…
Trong bài báo cáo này chúng em sẽ trình bày “Bài toán luồng cực đại trong mạng”
sử dụng thuật toán của Ford - Fulkerson (1962) để giải bài toán đặt ra
Chúng em xin gửi lời cảm ơn chân thành đến thầy Nguyễn Văn Hiệu đã hướng dẫn
và giúp đỡ chúng em hoàn thành đề tài này Trong quá trình nghiên cứu đề tài , do kiến thức chuyên ngành còn hạn chế nên chúng em vẫn còn nhiều thiếu sót khi tìm hiểu và trình bày về đề tài Rất mong nhận được sự góp ý của các thầy/cô để đề tài của chúng em được đầy đủ và hoàn chỉnh hơn
Trang 3
Mục lục
LỜI MỞ ĐẦU 2
I GIỚI THIỆU ĐỀ TÀI 4
I.1 Tên đề tài 4
I.2 Lý do chọn đề tài 4
I.3 Mục đích của đề tài 4
II CƠ SỞ LÝ THUYẾT 4
II.1 Ý tưởng 4
II.2 Cơ sở lý thuyết 4
II.2.1 Định nghĩa 4
II.2.2 Bài toán luồng cực đại 6
III TỔ CHỨC CẤU TRÚC DỮ LIỆU VÀ THUẬT TOÁN 7
III.1 Phát biểu bài toán 7
III.2 Cấu trúc dữ liệu 8
III.3 Thuật toán 8
IV CHƯƠNG TRÌNH VÀ KẾT QUẢ 16
IV.1 Tổ chức chương trình 16
IV.2 Ngôn ngữ cài đặt 22
IV.3 Kết quả: 22
IV.3.1 Giao diện chính của chương trình 22
IV.3.2 Kết quả thực thi của chương trình 23
IV.3.3 Nhận xét: 23
V KẾT LUẬN VÀ HƯỚNG PHÁT TRIỂN 23
V.1 Kết luận: 23
V.2 Hướng phát triển: 23
TÀI LIỆU THAM KHẢO 24
Trang 4I GIỚI THIỆU ĐỀ TÀI
I.1 Tên đề tài
“Tìm luồng cực đại trên mạng”
I.2 Lý do chọn đề tài
Bài toán tìm luồng cực đại trên mạng giúp chúng ta giải quyết được nhiều vấn đề trong thực tế, như xác định cường độ dòng lớn nhất của dòng vận tải giữa hai nút của một bản đồ giao thông, bài toán tìm luồng dầu lớn nhất có thể bơm từ tàu chở dầu vào bể chứa của một hệ thống đường ống dẫn dầu… Vì vậy, chúng em đã quyết định chọn đề tài này để có thể nghiên cứu thêm về nó, sau này áp dụng ra thực tế Ngoài ra, đây cũng là một đề tài không dễ, chúng
em muốn được thử thách, cải thiện năng lực của mình
I.3 Mục đích của đề tài
Giúp chúng em hiểu hơn về bài toàn luồng cực đại trên mạng
Nắm rõ về thuật toán Ford-Fullkerson
Tìm được luồng cực đại trên mạng
Nâng cao kĩ năng làm việc nhóm, kĩ năng tìm kiếm, đọc tài liệu
II CƠ SỞ LÝ THUYẾT
II.1 Ý tưởng
Ý tưởng xây dựng luồng cực đại như sau: xuất phát từ luồng nào đó, ta tìm đường đi (không định hướng) từ a đến z, tiến hành hiệu chỉnh giá trị luồng trên đường đi đó sao cho luồng mới có giá trị lớn hơn Nếu không tìm được đường đi như vậy thì luồng đó là luồng cực đại
Giả sử
P = (a, u, …, i, j, …, v, z)
là đường đi không có hướng từ a đến z
Nếu cạnh (i, j) là cung thì cung đó cùng hướng với P Ngược lại nếu (j, i) là cung thì cung đó ngược hướng với P
Tập các cung cùng hướng với P kí hiệu là P+
Tập các cung ngược hướng với P kí hiệu là P-
II.2 Cơ sở lý thuyết
II.2.1 Định nghĩa
1 Mạng[2]
Mạng là đồ thị có hướng G = (V,E,c) thỏa mãn :
Có duy nhất 1 đỉnh s không có cung đi vào gọi là đỉnh nguồn
Có duy nhất 1 đỉnh t không có cung đi ra gọi là đỉnh đích
Trang 5 Trọng số Cij của cung (i,j) là các số không âm gọi là khả năng thông qua của cung
Đồ thị liên thông yếu
Ví dụ : Đồ thị sau là mạng với đỉnh phát là s và đỉnh thu là t
Trang 6ai (a,i) G ( , )
Cho luồng f trên mạng G Giá trị của luồng f được định nghĩa là đại lượng
Val(f) = ∑(s,i) Gfsi = ∑(i,t) Gfit
II.2.1 Bài toán luồng cực đại
0 < fij Đặt
:= min{x x M}>0 Trong đó M là tập các giá trị cij –fij, (i, j)P+ và fij, (i, j)P-
Ta xây dựng luồng f’ như sau
ij '
(i, j) P: f (i, j) P
Trang 7Khi đó luồng f’ có giá trị lớn hơn giá trị của luồng f một lượng là , tức
Val(f) = ∑(s,i) Efsi = ∑(s,i) Efsi +
III.1 Phát biểu bài toán
Trong thực tế ta thường gặp bài toán gọi là bài toán tìm luồng cực đại như sau: Cho mạng G với nguồn s, đích t và khả năng thông qua cij, (i,j)G Trong số các luồng trên mạng
G, tìm luồng có giá trị lớn nhất
Input: Mạng G với đỉnh phát s, đỉnh thu t, khả năng thông qua của các cung
Cụ thể, trong file input.txt gồm:
Trang 8Output: Giá trị lớn nhất của luồng, F = { fij }với (i,j) E
Cụ thể, file output.txt gồm:
Hàng thứ nhất giá trị luồng cực đại
n hàng tiếp theo là giá trị luồng của các đỉnh tương ứng
III.2 Cấu trúc dữ liệu
Chương trình cài đặt sử dụng:
+ Mảng hai chiều để biểu diễn khả năng thông qua của các cung trên mạng, biểu diễn luồng trên các cung
+ Mảng một chiều để lưu vết đường tăng luồng (đặt nhãn cho đỉnh)
+ Cài đặt lớp Node để biểu diễn các đỉnh
+ Sử dụng kiểu file text để lấy dữ liệu và lưu kết quả có được từ chương trình
III.3 Thuật toán
- Thuật toán Ford- Fulkerson [2]
Đầu vào: Mạng G với nguồn a, đích z, khả năng thông qua C = (cij), (i, j)G
Trang 9Xác định đỉnh đánh dấu Trong số các đỉnh mang nhãn và chưa được đánh dấu chọn đỉnh vi với chỉ số i nhỏ nhất Nếu không tồn tại đỉnh như vậy, kết thúc, luồng F là cực đại Ngược lại gán v:= vi và đánh dấu đỉnh v
Bước (v):
Đặt nhãn các đỉnh chưa có nhãn kề đỉnh v:
Giả sử (,) là nhãn đỉnh v
Xét các cung có dạng (v,w), (w,v) theo thứ tự (v,v0), (v0,v), (v,v1),(v1,v) trong đó
w chưa được mang nhãn
Với cung dạng (v,w), nếu fvw < cvw, đặt nhãn đỉnh w là (v, min {, cvw - fvw}), nếu fvw = cvw , không đặt nhãn đỉnh w
Với cung dạng (w, v), nếu fwv >0, đặt nhãn đỉnh w là (v, min {, fwv}), nếu fwv = 0 , không đặt nhãn đỉnh w
Sang bước (iii)
Sau đó xoá tất cả các nhãn của các đỉnh trên P rồi quay lại bước (ii)
Minh họa thuật toán Ford- Fulkerson:
• Tìm luồng cực đại trên mạng G
a
Trang 10Bước 1: khởi tạo luồng ban đầu
Bước 2: Đặt nhãn cho đỉnh nguồn
Trang 11Bước 3: Kiểm tra nhãn của đích: nếu đích t có nhãn, sang bước (6), ngược lại
sang bước (4)
t chưa có nhãn, sang bước 4:
Bước 4: Xét các đỉnh đã mang nhãn, chọn đỉnh v để đánh dấu
Bước 5: Gán nhãn cho các đỉnh kề v
Quay lại bước 3: t chưa có nhãn, sang bước 4
Trang 12Bước 4: xác định đỉnh đã gán nhãn và đánh dấu:
Bước 5: gán nhãn các đỉnh kề v:
Quay lại bước 3 : t chưa có nhãn, sang bước 4:
Trang 13Bước 4: Xác định đỉnh cần đánh dấu:
Bước 5: gán nhãn cho các đỉnh kề v
Quay lại bước 3: t đã có nhãn, sang bước 6:
Trang 14Bước 6: Hiệu chỉnh luồng
Val(f) = 2
Xóa tất cả các nhãn trên P và quay lại bước 2
Trang 16IV CHƯƠNG TRÌNH VÀ KẾT QUẢ
#define INPUT "input.txt"
#define OUTPUT "output.txt"
int n; // so dinh
int beginNode, endNode; //dinh phat - dinh thu
int **c; //kha nang thong qua cua cac cung
int **f; //luong hien tai cua cac cung
Node *node; //cac dinh
int max_f; //gia tri luong cuc dai
bool Input(); //nhap du lieu tu file
void Init(); //khoi tao luong ban dau
void FordFulkerson();
void MakeLabel( int ); //gan nhan cac dinh ke dinh v
void EditFlow();
void Output(); //xuat ket qua ra file
void Destroy(); //giai phong bo nho
Trang 17//nhap so dinh tu file
inputFile >> n;
c = new int *[n];
//nhap gia tri tu file vao ma tran (kha nang thong qua cua cac cung)
for ( int i = 0; i < n; i++)
{
c[i] = new int [n];
for ( int j = 0; j < n; j++) {
inputFile >> c[i][j];
} }
Trang 18//khoi tao luong ban dau bang 0
for ( int i = 0; i < n; i++)
{
f[i] = new int [n];
for ( int j = 0; j < n; j++) {
f[i][j] = 0;
} }
node = new Node [n];
}
void ReSetLabel()
{
//cac dinh ban dau chua co nhan
for ( int i = 0; i < n; i++)
{
node[i].SetNode();
}
//gan nhan cho dinh phat
node[beginNode].SetNode(1, INF , beginNode);
//tim dinh v da gan nhan de danh dau
int v = 0; // index cua dinh v can danh dau trong node[]
Trang 19for (v = 0; v < n; v++) {
if (node[v].GetAttr() == 1) {
break ; }
}
if (v == n) {
return ; //ko con dinh nao de danh dau
if (i == endNode) {
break ; //break neu endNode da co nhan
} }
}
Trang 20if (c[i][ v ] > 0) //cung dang (i, v)
{
if (f[i][ v ] > 0) {
if (i == endNode) {
break ; //break neu endNode da co nhan
} }
} }
}
}
void EditFlow()
{
int delta = node[endNode].GetFlow();
max_f += delta; //tang luong cuc dai
int s = endNode;
while (s != beginNode)
{
int prev = node[s].GetPrev(); // dinh ke truoc dinh s
if (c[prev][s] > 0) // cung thuoc P+
Trang 21void Output()
{
ofstream outFile;
outFile.open( OUTPUT , ios ::out);
outFile << max_f << endl;
for ( int i = 0; i < n; i++)
{
for ( int j = 0; j < n; j++) {
outFile << left << setw(5) << f[i][j];
} outFile << endl;
int attr; // 0 - chua gan nhan; 1 - da gan nhan; 2 - da danh dau
int flow; // kha nang thong qua
int prev; // dinh ke truoc tren duong di
Trang 22this ->attr = attr ;
this ->flow = flow ;
this ->prev = prev ;
IV.2 Ngôn ngữ cài đặt
Bài toán được cài đặt bằng ngôn ngữ lập trình C++, bao gồm 5 file sau:
input.txt , Source.cpp, Node.h, Node.cpp, output.txt
IV.3 Kết quả:
IV.3.1 Giao diện chính của chương trình
Trang 23Chương trình không có giao diện giao tiếp, các dữ liệu vào và ra được lưu ở file input.txt, output.txt
IV.3.2 Kết quả thực thi của chương trình
Chương trình đã tìm được đúng luồng cực đại, song chưa có giao diện
V.1 Kết luận:
Thuật toán Ford-Fullkerson đã tìm được đúng luồng cực đại trên mạng, dựa vào bài toán luồng cực đại trên mạng ta có thể giải quyết một số vấn đề thực tế như vận chuyển dầu, luồng vận tải động nhất,
V.2 Hướng phát triển:
- Làm thêm giao diên, để người dùng có thể hình dung việc đánh dấu, gán nhãn cho các đỉnh diễn ra như thê nào, quan sát được quá trình tăng luồng, làm cho bài toán trở nên trực quan, hoàn thiện, đóng gói ứng dụng
Trang 24TÀI LIỆU THAM KHẢO
[1] Wikipedia :
https://en.wikipedia.org/wiki/Ford%E2%80%93Fulkerson_algorithm?fbclid=IwAR2nNls1qaVHFLzFQ-lsjojeMsoOTYzDlUW1yTQuUR-w7W3PmyZF_JPmoLw
[2] Slide bài giảng - Nguyễn Văn Hiệu – Khoa CNTT – ĐHBK Đà Nẵng