Nguồn đề bài: http://vn.spoj.com/problems/ASSIGN1/
1. Đề bài ASSIGN1 spoj
Có n người, n việc (1 < n ≤ 200). Người thứ i thực hiện công viêc j mất C[i,j] đơn vị thời gian. Giả sử tất cả bắt đầu vào thời điểm 0, hãy tìm cách bố trí mỗi công việc cho mỗi người sao cho thời điểm hoàn thành công việc là sớm nhất có thể.
Input
– Dòng đầu: N
– Tiếp theo là ma trận C[i,j]. (thuộc kiểu Integer)
Output
– Ghi thời điểm sớm nhất hoàn thành.
Example
Input:
4
10 10 10 2
10 10 3 10
4 10 10 10
10 5 10 10
Output:
5
2. Thuật toán ASSIGN1 SPOJ
– sử dụng chặt nhị phân thời gian nhỏ nhất thỏa mãn, giả sử đang chặt tới thời điểm mid, xây dựng một đồ thị gồm các cạnh có trọng số <=mid, sau đó tôi tìm xem có the ghép N công việc cho N người hay không (sử dụng kiến thức cặp ghép). Nếu thỏa mãn thì chặt nhỏ thời gian thỏa mãn, ngược lại chặt tăng thời gian thỏa mãn.
– Code cặp ghép các bạn có thể tìm trên site
3. code tham khảo C++ và pascal ASSIGN1 spoj
a. Code pascal
const fi=''; nmax=201; type data=integer; var f:text; A:array[0..nmax+1,0..nmax+1] of data; n:data; Q:array[0..nmax*nmax] of data; tr,MatchX,MatchY:array[0..nmax] of data; dau,cuoi,mid:data; procedure docfile; var i,j:data; begin assign(f,fi); reset(f); readln(f,n); for i:=1 to n do for j:=1 to n do read(f,a[i,j]); close(f); end; procedure them(x:data); begin inc(cuoi); q[cuoi]:=x; end; function lay:data; begin lay:=q[dau]; inc(dau); end; function BFS:data; var i,j,u,v:data; begin for i:=1 to n do tr[i]:=0; dau:=1; cuoi:=0; for i:=1 to n do if MatchX[i]=0 then them(i); while dau<=cuoi do begin u:=lay; for v:=1 to n do if (a[u,v]<=mid) and (tr[v]=0) then begin tr[v]:=u; if MatchY[v]=0 then exit(v); them(MatchY[v]); end; end; EXIT(0); 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; function slove:boolean; var i,j,d:data; begin for i:=1 to n do begin Matchx[i]:=0; Matchy[i]:=0; end; repeat d:=bfs; if d<>0 then Enlager(d); until d=0; for i:=1 to n do if Matchx[i]=0 then exit(false); exit(true); end; procedure xuli; var i,j:data; begin i:=0; j:=maxint; while i<j do begin mid:=(i+j) shr 1; if Slove then j:=mid else i:=mid+1; end; writeln(i); end; begin docfile; xuli; end.
b. Code c++
#include<cstdio> #include<cstring> #include<climits> #include<vector> #include<queue> using namespace std; int c[201][201]; int matchX[201]={0},matchY[201]={0},d[201],n,tim; int find_match(int x) { queue<int> q; q.push(x); memset(d,0,sizeof d); while(!q.empty()) { int u=q.front();q.pop(); for(int v=1;v<=n;++v) if(c[u][v]<=tim && !d[v]) { d[v]=u; if(!matchY[v]) return v; q.push(matchY[v]); } } return 0; } void enlarge(int y) { int x,next; while(y) { x=d[y]; next=matchX[x]; matchX[x]=y; matchY[y]=x; y=next; } } bool check(int mid) { int i,j; tim=mid; memset(matchX,0,sizeof matchX); memset(matchY,0,sizeof matchY); for(i=1;i<=n;++i) if(!matchX[i]) { j=find_match(i); if(j) enlarge(j); } for(i=1;i<=n;++i) if(!matchX[i]) return 0; return 1; } int main() { //freopen("test.inp","r",stdin); int i,j; scanf("%d",&n); for(i=1;i<=n;++i) for(j=1;j<=n;++j) scanf("%d",&c[i][j]); i=0;j=INT_MAX; while(i<j) { int mid=(i+j)>>1; if(check(mid)) j=mid; else i=mid+1; } printf("%d",i); }
code cặp ghép là gì, site là gì hả a?
là bài này nè em.
https://kienthuc24h.com/hungari-cap-ghep-cuc-dai-co-trong-so-cuc-tieu
đọc trog sách 1 số vấn đề trong tin học là hiểu