1. LỜI MỞ ĐẦU 2
2. MỘT SỐ KHÁI NIỆM CƠ BẢN 2
2.1. cấu trúc đồ thị 2
2.2. Phép duyệt đồ thị 3
2.3. Đồ thị và hàm chi phí 4
2.4. Đồ thị và quan hệ 6
2.5. Cây và cây có gốc 8
2.6. Biểu diễn đồ thị và cây 10
3. TÌM HIỂU MỘT SỐ CÁCH PHÂN LOẠI BÀI TOÁN ĐỒ THỊ 11
3.1. Một số cách phân loại bài toán đồ thị 11
3.1.1. Phân loại theo chương trình khung của Bộ GD&ĐT 11
3.1.2. Phân loại theo logic lý thuyết đồ thị 12
3.1.3. Phân loại bài toán theo nhóm các thuật toán trên đồ thị 13
3.2. Nhận xét và lựa chọn của chúng tôi 14
271 trang |
Chia sẻ: vivian | Lượt xem: 1453 | Lượt tải: 0
Bạn đang xem trước 20 trang tài liệu Bài giảng Phân loại bài toán đồ thị, để xem tài liệu hoàn chỉnh bạn click vào nút DOWNLOAD ở trên
:= u;
D[u] := sv;
While dau<=cuoi do
Begin
u := queue[dau];
inc(dau);
For v:=1 to n do
If A[u,v] and (D[v]=0) then
Begin
Inc(cuoi);
queue[cuoi] := v;
D[v] := sv;
End;
End;
End;
Procedure Timsvlt;
var i: integer;
Begin
Sv := 0;
fillchar(D, sizeof(d), 0);
Fillchar(D,sizeof(D),0);
for i:=1 to n do
if D[i]=0 then
begin
inc(sv);
BFS(i);
end;
End;
Procedure Inkq;
Var i, j: integer;
Begin
Assign(OutPut,fo);
Rewrite(OutPut);
writeln(sv);
For i:=1 to sv do
Begin
For j:=1 to N do
If D[j]=i then Write(j,' ');
Writeln;
end;
Close(Output);
End;
BEGIN
ReadFile;
Timsvlt;
Inkq;
END.
Bài 4:
Cho bảng hình chữ nhật chia thành m×n ô vuông đơn vị, mỗi ô vuông có ghi số 0 hoặc 1. Một miền 0 của bảng là tập hợp các ô chung đỉnh chứa số 0. Hãy tính số miền 0 của bảng và diện tích của từng miền 0.
Dữ liệu vào từ file văn bản MIEN0.INP
Dòng 1: Ghi m, n (1<m, n≤100).
M dòng tiếp theo thể hiện bảng số theo thứ tự từ trên xuống dưới, mỗi dòng n số theo thứ tự từ trái qua phải.
Kết quả ghi ra file MIEN0.OUT
Dòng 1: Ghi số lượng miền 0.
Dòng 2: ghi diện tích của các miền 0
Ví dụ :
MIEN0.INP
MIEN0.OUT
8 10
0 1 0 0 0 0 0 0 1 0
1 1 0 0 0 0 0 0 1 0
0 0 0 1 1 0 0 0 1 0
1 1 1 0 1 1 0 0 1 0
0 0 1 1 0 0 0 0 1 0
0 0 0 1 1 1 1 1 1 0
1 1 0 1 0 0 0 1 0 1
0 0 0 1 0 0 1 0 1 0
4
1 25 14 9
Const Max = 100;
Fi = 'MIEN0.INP';
Fo = 'MIEN0.OUT';
dc: Array[1..8] of integer = ( 0, 1, 1, 1, 0,-1,-1,-1);
dd: Array[1..8] of integer = (-1,-1, 0, 1, 1, 1, 0,-1);
Var A, D: Array[1..Max,1..Max] of integer;
QUEUE : Array[1..Max*Max] of Record
d,c : integer;
End;
DT : Array[1..Max*Max] of Integer;
N, M , dau, cuoi, sv : integer;
Procedure DocF;
Var i,j : integer;
Begin
Assign(Input,Fi);
Reset(Input);
Readln(M,N);
For i:=1 to M do
For j:=1 to N do Read(A[i,j]);
Close(Input);
End;
Procedure BFS(i,j : integer);
Var k,dong,cot,u,v : integer;
Begin
Dau:=1;
Cuoi:=1;
QUEUE[cuoi].d := i;
QUEUE[cuoi].c := j;
D[i,j] := sv;
DT[SV]:=1;
While dau<=cuoi do
Begin
dong := QUEUE[dau].d;
cot := QUEUE[dau].c;
inc(dau);
For k:=1 to 8 do
Begin
u := dong + Dd[k];
v := cot + Dc[k];
If (u>0) and (u0) and (v<=N) then
If (A[u,v]=0) and (D[u,v]=0) then
Begin
Inc(cuoi);
QUEUE[cuoi].d := u;
QUEUE[cuoi].c := v;
D[u,v] := sv;
Inc(DT[sv]);
End;
End;
End;
End;
Procedure Timsvlt;
var i, j: integer;
Begin
Sv := 0;
fillchar(D, sizeof(d), 0);
fillchar(DT, sizeof(DT), 0);
Fillchar(D,sizeof(D),0);
for i:=1 to m do
for j:=1 to n do
if (a[i,j]=0) and (D[i,j]=0) then
begin
inc(sv);
BFS(i,j);
end;
End;
Procedure Inkq;
Var i: integer;
Begin
Assign(OutPut,fo);
Rewrite(OutPut);
writeln(sv);
For i:=1 to sv do Write(DT[i],' ');
Close(Output);
End;
BEGIN
DocF;
Timsvlt;
Inkq;
END.
Bài 5:
Một lâu đài được chia thành m×n modul vuông (1<m, n<=50). Mỗi modul vuông có từ 0 đến 4 bức tường. Hãy viết chương trình tính :
1 - Lâu đài có bao nhiêu phòng ?
2 - Diện tích phòng lớn nhất là bao nhiêu ?
3 - Bức tường nào cần loại bỏ để phòng càng rộng càng tốt ?
Dữ liệu vào từ tệp văn bản LAUDAI.INP
Dòng 1: ghi số lượng các môdul theo hướng Bắc-Nam và số lượng các modul theo hướng Đông Tây.
Trong các dòng tiếp theo, mỗi modul được mô tả bởi 1 số (0 £p£15). Số đó là tổng của : 1 (= tường phía Tây ), 2 (=tường phía Bắc ) ,4 (=tường phía Đông ) , 8 ( = tường phía Nam) .
Các bức tường ở bên trong được xác định hai lần ; bức tường phía Nam trong modul (1,1) đồng thời là bức tường phía Bắc trong modul (2,1)
Kết quả ghi ra tệp văn bản LAUDAI.OUT
Dòng 1: ghi số lượng phòng.
Dòng 2: ghi diện tích của phòng lớn nhất (tính theo số modul )
Dòng 3: ghi bức tường cần loại bỏ (trước tiên là hàng sau đó là cột của modul có tường đó ) và dòng cuối cùng là hướng của bức tường .
Ví dụ:
1 2 3 4 5 6 7 N (Bắc)
®
1
W (Tây) E (Đông)
2
3
S (Nam)
4
Mũi tên chỉ bức tường cần loại bỏ theo kết quả ở ví dụ
Const NMax = 50;
Fi = 'LAUDAI.INP';
Fo = 'LAUDAI.OUT';
dd: Array[0..3] of integer = ( 0,-1, 0, 1);
dc: Array[0..3] of integer = (-1, 0, 1, 0);
h: array[0..3] of char=('W','N', 'E', 'S');
Var A, D: Array[1..NMax,1..NMax] of integer;
queue : Array[1..NMax*NMax] of Record
d,c : integer;
End;
DT : Array[1..NMax*NMax] of Integer;
N, M, dau, cuoi, sp, MaxDT, i0, j0, k0: integer;
Procedure DocF;
Var i,j : integer;
Begin
Assign(Input,Fi);
Reset(Input);
Readln(M,N);
For i:=1 to M do
For j:=1 to N do Read(A[i,j]);
Close(Input);
End;
Procedure BFS(i,j : integer);
Var k,dong,cot,u,v : integer;
Begin
Dau:=1;
Cuoi:=1;
queue[cuoi].d := i;
queue[cuoi].c := j;
D[i,j] := sp;
DT[sp]:=1;
While dau<=cuoi do
Begin
dong := queue[dau].d;
cot := queue[dau].c;
inc(dau);
For k:=0 to 3 do
Begin
u := dong + Dd[k];
v := cot + Dc[k];
If (u>0) and (u0) and (v<=N) then
If ((A[dong,cot] shr k) and 1 =0) and (D[u,v]=0) then
Begin
Inc(cuoi);
queue[cuoi].d := u;
queue[cuoi].c := v;
D[u,v] := sp;
Inc(DT[sp]);
End;
End;
End;
End;
procedure TimDtMax;
var i: integer;
begin
MaxDT:=0;
for i:=1 to sp do
if MaxDT<DT[i] then MaxDT:=DT[i];
end;
procedure TimTuong;
var i, j, k, max, u, v: integer;
begin
max:=0;
for i:=1 to m-1 do
for j:=1 to n-1 do
for k:=2 to 3 do
begin
u:=i+dd[k];
v:=j+dc[k];
if ((a[i,j] shr k) and k =1) and (D[i,j]D[u,v]) then
if max < DT[D[i,j]]+DT[D[u,v]] then
begin
max:=DT[D[i,j]]+DT[D[u,v]];
i0:=i;
j0:=j;
k0:=k;
end;
end;
end;
Procedure Timsvlt;
var i, j: integer;
Begin
sp := 0;
fillchar(DT, sizeof(DT), 0);
Fillchar(D,sizeof(D),0);
for i:=1 to m do
for j:=1 to n do
if D[i,j]=0 then
begin
inc(sp);
BFS(i,j);
end;
End;
Procedure Inkq;
Var i: integer;
Begin
Assign(OutPut,fo);
Rewrite(OutPut);
writeln(sp);
Writeln(MaxDT);
writeln(i0,' ', j0, ' ', h[k0]);
Close(Output);
End;
BEGIN
DocF;
Timsvlt;
TimDtMax;
TimTuong;
Inkq;
END.
Bài 6:
Cho một lưới hình chữ nhật kích thước m´n gồm các ô vuông đơn vị, mỗi ô được tô 1 trong 6 màu ký hiệu màu 1 , màu 2 màu 6. Giả thiết màu của 2 ô trái trên và phải dưới là khác nhau. Hai ô chung cạnh cùng thuộc một miền nếu cùng màu . Người A đứng ở miền có chứa ô góc trái trên, người B đứng ở miền có chứa ô phải dưới . Hai người chơi lần lượt, đến lượt mình người chơi có thể tô lại màu của miền mà mình đang đứng. Trò chơi kết thúc khi hai người đứng ở hai miền cạnh nhau (chung nhau ít nhất một cạnh của một ô vuông). Tính số lượt đi ít nhất để trò chơi đó kết thúc.
Giới hạn: 1 ≤ m, n ≤ 100. Số lượng miền ≤ 100.
Dữ liệu vào từ tệp văn bản DOIMAU.INP:
Dòng đầu: ghi hai số m , n.
M dòng tiếp theo, số thứ j của dòng j ghi số hiệu màu của ô [i, j].
Kết quả ghi ra tệp văn bản DOIMAU.OUT: ghi 1 số duy nhất là số lượt đi ít nhất để trò chơi kết thúc.
Ví dụ:
DOIMAU.INP
DOIMAU.OUT
4 3
1 2 2
2 2 1
1 4 3
1 3 2
3
Phân tích:
+ Loang từ ô [1, 1] để tìm số miền (sm) .
1
2
2
2
2
3
4
5
6
4
7
8
+ Xây dựng véc tơ V màu của từng miền
V=
1
2
3
4
5
6
7
8
1
2
1
1
4
3
3
2
5
1
2
3
4
6
7
8
+ Xây dựng đồ thị gồm sm đỉnh, xem một miền là một đỉnh của đồ thị. Giữa hai đỉnh có cạnh nối nếu hai miền đó có chung nhau ít nhất một cạnh của một ô vuông.
+ Tìm đường đi ngắn nhất
từ đỉnh 1 đến đỉnh sm
Trong thủ tục BFS, tại mỗi bước, ta thăm một đỉnh đầu danh sách (giả sử đỉnh đó là đỉnh u), loại nó ra khỏi danh sách và cho những đỉnh v, chưa “xếp hàng” kề với u xếp hàng thêm vào cuối danh sách, tô màu đỉnh v giống màu đỉnh u, đồng thời cho các đỉnh kề với đỉnh v có màu giống với đỉnh u, chưa xếp “xếp hàng” thêm vào cuối danh sách.
{$MODE OBJFPC}
Const Max = 100;
Fi = 'DOIMAU.INP';
Fo = 'DOIMAU.OUT';
dd: Array[1..4] of integer = ( 0,-1, 0, 1);
dc: Array[1..4] of integer = (-1, 0, 1, 0);
Var A, B, D: Array[1..Max,1..Max] of integer;
Queue : Array[1..Max*Max] of record
d, c: integer;
end;
len: array[1..max] of integer;
mau: array[1..max] of integer;
N, M, sv : integer;
Procedure DocF;
Var i,j : integer;
Begin
Assign(Input,Fi);
Reset(Input);
Readln(M,N);
For i:=1 to M do
For j:=1 to N do Read(A[i,j]);
fillchar(b, sizeof(b),0);
fillchar(mau, sizeof(mau),0);
Close(Input);
End;
Procedure BFS(i,j : integer);
Var k,dong,cot,u,v, dau, cuoi: integer;
Queue : Array[1..Max*Max] of record
d, c: integer;
end;
Begin
Dau:=1;
Cuoi:=1;
Queue[cuoi].d := i;
Queue[cuoi].c := j;
D[i,j] := sv;
mau[sv]:=a[i,j];
While dau<=cuoi do
Begin
dong := Queue[dau].d;
cot := Queue[dau].c;
inc(dau);
For k:=1 to 4 do
Begin
u := dong + Dd[k];
v := cot + Dc[k];
If (u>0) and (u0) and (v<=N) then
begin
If (a[u,v]=a[i,j])and(D[u,v]=0) then
Begin
Inc(cuoi);
Queue[cuoi].d := u;
Queue[cuoi].c := v;
D[u,v] := sv;
End;
if (a[u,v]a[i,j]) and (D[u,v]0) then
begin
b[d[u,v],sv]:=1;
b[sv,d[u,v]]:=1;
end;
end;
End;
End;
End;
Procedure Timsvlt;
var i, j: integer;
Begin
Sv := 0;
fillchar(D, sizeof(d), 0);
for i:=1 to m do
for j:=1 to n do
if D[i,j]=0 then
begin
inc(sv);
BFS(i,j);
end;
End;
procedure BFS1;
Var k, u, v, dau, cuoi : integer;
queue: array[1..max] of integer;
Begin
Dau:=1;
Cuoi:=1;
Queue[cuoi]:=1;
len[1]:=1;
While dau<=cuoi do
Begin
u:=queue[dau];
inc(dau);
For v:=1 to sv do
if (b[u,v]=1) and (len[v]=0) then
Begin
Inc(cuoi);
Queue[cuoi]:=v;
len[v]:=len[u]+1;
mau[v]:=mau[u];
for k:=1 to sv do
if (b[v,k]=1)and(mau[k]=mau[u])and(len[k]=0) then
begin
inc(cuoi);
queue[cuoi]:=k;
len[k]:=len[v];
end;
End;
End;
End;
Procedure Inkq;
Var i, j: integer;
Begin
Assign(OutPut,fo);
Rewrite(OutPut);
{writeln(sv);
For i:=1 to m do
begin
for j:=1 to n do Write(D[i,j],' ');
writeln;
end;}
write(len[sv]-1);
Close(Output);
End;
BEGIN
DocF;
Timsvlt;
BFS1;
Inkq;
END.
File đính kèm:
- Do Thi.doc