Đồ thị với số đỉnh lớnĐỗ Đức Đông Bạn đã bao giờ giải bài toánđồ thị mà với số đỉnh rất lớn chưa?. Sau đây tôi xin giới thiệu hai bài toán cơ bảnnhất và áp dụng nhiều nhất của đồ thị với
Trang 1Đồ thị với số đỉnh lớn
Đỗ Đức Đông
Bạn đã bao giờ giải bài toánđồ thị mà với số đỉnh rất lớn chưa? Nếu đồ thị đó có số cạnh nhỏ thì không cóvấn đề gì Chỉ cần lưu các cạnh thành danh sách kề rồi giải Nhưng nếu
số cạnhcũng rất lớn thì sao?Việc lưu dữ liệu rất nhiều khó khăn Ta phải biết chọnlọc, tổ chức dữ liệu để giải Sau đây tôi xin giới thiệu hai bài toán cơ bảnnhất và áp dụng nhiều nhất của đồ thị với số đỉnh, số cạnh lớn
Bài toán 1: Số vùng liên thông
Cho một đồ thị vô hướng gồmN(N<=5000) đỉnh, cạnh Ta định nghĩa một vùng liên thông là tập hợp các đỉnhcủa đồ thị mà 2 đỉnh bất kỳ của vùng đều đi được tới nhau trực tiếp hay thôngqua các đỉnh khác của vùng Hãy tìm số vùng liên thông của đồ thị
Dữ liệu vào trong file BAI1.INP
- Dòng thứ nhất là hai số N,M
- M dòng sau mỗi dòng gồm haisố là tên hai đỉnh mà giữa chúng cócạnh nối trực tiếp Kết quả ra file BAI1.OUT
-Gồm một số duy nhất là sốvùng liên thông của đồ thị
Ví dụ
BAI1.INP BAI1.OUT
5 3
1 2
4 5
3 2
2
Phân tích bài toán
Số đỉnh tối đa của đồ thị N=5000 là rất lớn! Sốcạnh tối đa lên tới N*N/2=12500000
Vì vậy file dữ liệu sẽ rất lớn Việc lưu giữtheo cách thông thường là không khả thi
Trang 2Thuật toán
Dùng một mảng V[1 N].Khởi trịV[i]=i , i=1, , N
Với bài toán này ta sẽ vừa đọcvừa xử lý
Giả sử ta bắt đầu đọc đến cạnhthứ k là cạnh (x,y)
Tức là đồ thị hiện tại gồm Nđỉnh và k-1 cạnh đầu Phần tử thứ i của mảng V, V[i] sẽ cho
ta biết rằng đỉnh ilà vùng V[i] Đọc cạnh thứ k là cạnh (x, y)
Công việc hiện tại là xử lýthông tin vừa nhận(cạnh thứ k) Nếu là thông tin thừa thì loại
bỏ, còn nếu làthông tin có ích thì thu nhận và mã hoá thông tin
Nếu V[x]=V[y] thì đây là thông tin thừa Vì ta đã biếtrằng hai đỉnh x, y đã cùng thuộc một vùng liên thông rồi thì không cần cạnh thứk (x, y) này nữa
Nếu V[x]<>V[y] thì đây là thông tin có ích Ta sẽthu nhận thông tin này và mã hoá Cách mã hoáthông tin:Ta sẽ nối hai vùng V[x],V[y] làm một vùng tức là cho tất cả các đỉnhcó tên vùng là V[y] thành vùng có tên là V[x](hoặc cho tất cả các đỉnh có tênvùng là V[x] thành vùng có tên là V[y])
Sau khi xử lý song M cạnh takiểm tra xem có tất cả bao nhiêu vùng số số khác nhau trong mảng V) Có mộtcách khác để tìm số vùng liên thông ta dùng biến đếm dem để đếm số cạnh được xửlý Mỗi lần nối 2 vùng thì bị giảm mất một vùng Như vậy số vùng liên thông củađồ thị = N- dem
Sau đây là chương trình hoànchỉnh thể hiện thuật toán trên
Program So_vung_lien_thong;
Uses crt;
Const max =5000;
F= 'BAI1.INP' ;
Fo= 'BAI1.OUT' ;
Var V:Array[1 Max]of Integer;
N,M,dem :Longint;
Procedure lam;
Trang 3Var F :text;
x,y,i,j :integer;
k :Longint;
Begin
Dem:=0;
Assign(f,fi);
Reset(f);
Readln(f,N,M);
For k:=1 to M do
Begin
Readln(f,x,y);
IfV[x]<>V[y] then {Thông tincó ích}
Begin
j:=V[y];
inc(dem);
For i:=1 to N do {Nối hai vùnglàm một vùng}
If V[i]=j then V[i]:=V[x];
End;
End;
Close(f);
End;
Procedure ghikq;
Var F ;
Trang 4Assign(f,fo);
Rewrite(f);
Write(f,N-dem));
Close(f);
End;
BEGIN
Lam;
Ghikq;
END
Đánh giá, nhận xét thuật toán :
Độ phức tạp thuật toán: Bạn dễ dàng thấy số cạnh đượcxử lý sẽ không vượt quá N-1 vì vậy độ phức tạp là N*N
Việc nối hai vùng liên thông chưa tốt bạn có thể tổchức dữ liệu khéo hơn và nối hai vùng liên thông một cách hiệu quả hơn sẽ làmtăng tốc độ chương trình
Bạn hãy để ý xem nếu đã xử lý N-1 cạnh(dem=N-1) thì cóthể ngắt chương trình vì khi đó
ta có thể kết luân được rằng đồ thị liênthông,thời gian chạy sẽ nhanh hơn
Bài toán 2: Tìm đường đi từ s tới t trong đồ thị vô hướng lớn
Cho một đồ thị vô hướng gồmN(N<=5000)đỉnh,M cạnh.Cho đỉnh xuất phát s và đỉnh đích t.Tìm một đường đitừ s tới t
Dữ liệu vào trong fileBAI2.INP
- Dòng thứ nhất là 4 sốN,M,s,t
- M dòng sau mỗi dòng gồm haisố là tên hai đỉnh mà giữa chúng cócạnh nối trực tiếp Kết quả ra file BAI2.OUT
-Dòng 1 là số w là số đỉnhtrong đường đi(w=0 nếu không có đường đi)
Trang 5-Nếu w>0 thì dòng 2 gồm wsố là các đỉnh lần lượt trong đường đi từ s tới t.
Ví dụ
BAI2.INP BAI2.OUT
5 4 1 5
1 4
3 2
5 4
4 3
3
1 4 5
Thuật toán
Ta dễ nhận thấy rằng bài toán có nghiệm khi s,tcùng thuộc một vùng liên thông
Và ta nhận thấy rằng dem cạnhđược xử lý là các cạnh tinh tuý được lọc ra từ đống dữ liệu thô sơ của đầubài.Chỉ cần dùng những cạnh như vậy ta có thể tìm được một đường đi từ
đỉnh stới đỉnh t.Các cạnh đó là cái khung(chưachắc là cây khung) của đồ thị đã cho Bây
giờ ta lưu lại dem cạnh đó rồi dùng danh sách kề và thuật toán tìm kiếmtheo chiều sâu hoặc chiều rộng để giải một cách đơn giản
Chú ý:Bạn đọc hãy để ý một điều kiện để ngắt nhanh và giảm độ phứctạp bài toán đó là
điều kiện: V[s]=V[t].Tức là 2 đỉnh s,t đã cùng 1 vùng liênthông rồi,đã đủ cạnh để tìm đường đi
Lời giải xin dành cho bạn đọc
Bạn nào có thắc mắc hoặc cầnchương trình bài 2 hãy liên hệ với toà soạn hay với tôi theo địa chỉ : Đỗ ĐứcĐông K45C-CN-ĐHQGHN (034.821773)