KM似乎還是有點難以理解,看了半天資料仍有半懂不懂的感覺,或許以後多想想、畫畫,做些題能加深理解吧,當初學匈牙利的時候就是這樣。
相關資料
二分圖帶權匹配 KM演算法與費用流模型建立
丘位元的問題——求二分圖最大權匹配的演算法
nocow上的講解
題目:ural1076
原題:http://acm.timus.ru/problem.aspx?space=1&num=1076
譯題:http://www.nocow.cn/index.php/Translate:URAL/1076
題解:http://www.nocow.cn/index.php/URAL/1076
我的KM是抄nocow上的題解的,只不過出於習慣改了一個變數名。費用流的思路也是按nocow上的,計算出i種箱子裝j種垃圾的費用然後求最小費用。根據自己的理解按照KM上的統計所有垃圾量-最大費用的程式也寫了一個,不過陷入死迴圈中,有時間再調試吧。
我的ural1076 KM演算法程式
const oo=199305080; maxn=200;var lx,ly,link:array[0..maxn] of longint; w:array[0..maxn,0..maxn] of longint; i,j,k,m,n,d,tot:longint; x,y:array[0..maxn] of boolean;function max(a,b:longint):longint;begin if a<b then exit(B) else exit(a);end;procedure init;begin readln(n); for i:=1 to n do for j:=1 to n do begin read(w[i,j]); inc(tot,w[i,j]); end;end;function dfs(v:longint):boolean;var i:longint;begin if v=0 then exit(true); x[v]:=true; for i:=1 to n do if (y[i]=false) and (lx[v]+ly[i]=w[v,i]) then begin y[i]:=true; if dfs(link[i]) then begin link[i]:=v; exit(true); end end; exit(false);end;procedure main;begin for i:=1 to n do for j:=1 to n do lx[i]:=max(lx[i],w[i,j]); for k:=1 to n do while true do begin fillchar(x,sizeof(x),0); fillchar(y,sizeof(y),0); if dfs(k) then break; d:=oo; for i:=1 to n do if x[i] then for j:=1 to n do if (not y[j]) and (lx[i]+ly[j]-w[i,j]<d) then d:=lx[i]+ly[j]-w[i,j]; for i:=1 to n do begin if x[i] then dec(lx[i],d); if y[i] then inc(ly[i],d); end end;end;procedure print;begin for i:=1 to n do dec(tot,w[link[i],i]); writeln(tot);end;begin init; main; print;end.來一個費用流:
const maxn=400; oo=199305080;var c,cost,w:array[0..maxn,0..maxn] of longint; flow,i,j,k,m,n,mincost,tot,s,t,pre,now,sum:longint; path:array[0..maxn] of longint; q,dist:array[0..100000] of longint; flag:array[0..10000] of boolean;function spfa:boolean;var i,j,k,head,tail:longint;begin head:=0; tail:=1; q[1]:=s; fillchar(flag,sizeof(flag),0); flag[s]:=true; for i:=1 to tot do dist[i]:=oo; dist[s]:=0; while head<tail do begin inc(head); i:=q[head]; flag[i]:=false; for j:=1 to tot do begin if (c[i,j]>0) and (dist[j]>dist[i]+cost[i,j]) then begin dist[j]:=dist[i]+cost[i,j]; path[j]:=i; if not flag[j] then begin flag[j]:=true; inc(tail); q[tail]:=j; end; end; end; end; exit(dist[t]<>oo);end;procedure init;begin readln(n); for i:=1 to n do begin sum:=0; for j:=1 to n do begin read(w[i,n+j]); inc(sum,w[i,n+j]); end; for j:=1 to n do begin cost[i,n+j]:=sum-w[i,n+j]; cost[n+j,i]:=-cost[i,n+j]; c[i,n+j]:=1; end; end; s:=n*2+1; t:=n*2+2; tot:=t; for i:=1 to n do c[s,i]:=1; for i:=1 to n do c[n+i,t]:=1;end;function min(a,b:longint):longint;begin if a<b then exit(a) else exit(b);end;procedure main;begin while spfa do begin now:=t; flow:=oo; while now<>s do begin pre:=path[now]; flow:=min(flow,c[pre,now]); now:=pre; end; now:=t; while now<>s do begin pre:=path[now]; dec(c[pre,now],flow); inc(c[now,pre],flow); inc(mincost,flow*cost[pre,now]); now:=pre; end; end;end;procedure print;begin writeln(mincost);end;begin init; main; print;end.