Nguồn đề bài: http://vn.spoj.com/problems/MATCH2/
1. Đề bài Cặp ghép cực đại có trọng số cực tiểu
Cho đồ thị hai phía G = (X U Y, E); Các đỉnh của X ký hiệu là x1, x2, …, xn, các đỉnh của Y ký hiệu là y1, y2, …, yn. Mỗi cạnh của G được gán một trọng số không âm. Một bộ ghép đầy đủ trên G là một tập n cạnh thuộc E đôi một không có đỉnh chung. Trọng số của bộ ghép là tổng trọng số các cạnh nằm trong bộ ghép.
Ràng buộc: Luôn tồn tại ít nhất một bộ ghép đầy đủ trên G.
Chú ý dùng Eof chứ không dùng SeekEof
Input
• Dòng 1: Chứa số n (1 ≤ n ≤ 200)
• Các dòng tiếp theo, mỗi dòng chứa 3 số nguyên i, j, c cho biết có một cạnh (xi, yj) và trọng số cạnh đó là c (0 ≤ c ≤ 200).
Output
• Dòng 1: Ghi trọng số bộ ghép tìm được
• n dòng tiếp, mỗi dòng ghi hai số (u, v) tượng trưng cho một cạnh (xu, yv) được chọn vào bộ ghép.
Example
Input:
4
1 1 0
1 2 0
2 1 0
2 4 2
3 2 1
3 3 0
4 3 0
4 4 9
Output:
3
1 1
2 4
3 2
4 3
2. Code tham khảo thuật toán Hungari , MATCH2 spoj
Bài này các bạn vui lòng coi thuật toán chi tiết trong sách Lê Minh Hoàng.
const fi=''; nmax=200; vc=100000000; type data=longint; var f:text; A:array[0..nmax+1,0..nmax+1] of data; Fx,Fy,MatchX,MatchY,tr:array[0..nmax+1] of data; Q:array[0..nmax*nmax] of data; ddx,ddy:array[0..nmax+1] of boolean; dau,cuoi,start,finish:data; n:data; procedure docfile; var i,j,u,v,c:data; begin assign(f,fi); reset(f); readln(f,n); for i:=1 to n do for j:=1 to n do a[i,j]:=vc; while not eof(f) do begin readln(f,u,v,c); a[u,v]:=c; end; close(f); end; procedure init; var i,j:data; begin fillchar(MatchX,sizeof(matchx),0); MatchY:=MatchX; for i:=1 to n do begin fx[i]:=vc; for j:=1 to n do if fx[i]>a[i,j] then fx[i]:=a[i,j]; end; for i:=1 to n do begin fy[i]:=vc; for j:=1 to n do if a[i,j]-fx[i]<fy[i] then fy[i]:=a[i,j]-fx[i]; end; end; function get(i,j:data):data; begin get:=a[i,j]-fx[i]-fy[j]; end; procedure themvao(x:data); begin inc(cuoi); q[cuoi]:=x; end; function layra:data; begin layra:=q[dau]; inc(dau); end; procedure bfs; var u,v,j,i:data; begin fillchar(tr,sizeof(tr),0); dau:=1; cuoi:=0; themvao(start); while dau<=cuoi do begin u:=layra; for v:=1 to n do if (tr[v]=0) and (get(u,v)=0) then begin tr[v]:=u; if matchy[v]=0 then begin finish:=v; exit; end; themvao(matchy[v]); end; end; end; procedure enlager(u:data); var v,next:data; begin repeat v:=tr[u]; next:=MatchX[v]; MatchX[v]:=u; MatchY[u]:=v; u:=next; until u=0; end; procedure subX_addY; var i,j,delta:data; begin fillchar(ddx,sizeof(ddx),false); ddy:=ddx; ddx[start]:=true; for i:=1 to n do if tr[i]<>0 then begin ddx[MatchY[i]]:=true; ddy[i]:=true; end; delta:=vc; for i:=1 to n do if ddx[i] then for j:=1 to n do if (not ddy[j]) and (delta>get(i,j)) then delta:=get(i,j); for i:=1 to n do begin if ddx[i] then fx[i]:=fx[i]+delta; if ddy[i] then fy[i]:=fy[i]-delta; end; end; procedure xuli; var i,j,res:data; begin for i:=1 to n do begin start:=i; finish:=0; repeat bfs; if finish=0 then subx_addy; until finish<>0; enlager(finish); end; res:=0; for i:=1 to n do if MatchX[i]<>0 then inc(res,a[i,Matchx[i]]); writeln(res); for i:=1 to n do if MatchX[i]<>0 then writeln(i, ' ',MatchX[i]); end; begin docfile; init; xuli; end.
anh thiệt là, em đã mò từ bài kia sang bài này. h lại. ———————- haizzz
em đọc trong sách những vấn đề gì gì đó ở bài viết tổng tài liệu chuyên tin cần thiết
cặp ghép làm bằng luồng dc á