用uoj80的题面了:
从前一个和谐的班级,有 nlnl 个是男生,有 nrnr 个是女生。编号分别为 1,…,nl1,…,nl 和 1,…,nr1,…,nr。
有若干个这样的条件:第 vv 个男生和第 uu 个女生愿意结为配偶,且结为配偶后幸福程度为 ww。
请问这个班级里幸福程度之和最大是多少?
输入格式
第一行三个正整数,nl,nr,mnl,nr,m。
接下来 mm 行,每行三个整数 v,u,wv,u,w 表示第 vv 个男生和第 uu 个女生愿意结为配偶,且幸福程度为 ww。保证 1≤v≤nl1≤v≤nl,1≤u≤nr1≤u≤nr,保证同一对 v,uv,u 不会出现两次。
输出格式
第一行一个整数,表示幸福程度之和的最大值。
接下来一行 nlnl 个整数,描述一组最优方案。第 vv 个整数表示 vv 号男生的配偶的编号。如果 vv 号男生没配偶请输出 00。
样例一
input
2 2 3
1 1 100
1 2 1
2 1 1
output
100
1 0
限制与约定
1≤nl,nr≤400,1≤m≤160000,1≤w≤109。
时间限制:1s1s
空间限制:256MB
一种简单一点的方法就是最大费用流或者用相反数作为费用跑最小费用流,但是比km算法慢。
但实现时要注意不是求最大费用最大流,而是当最长增广路<=0时就停止。
这个代码在uoj是tle的,那个好像必须用km,但我不会啦。
1 program rrr(input,output); 2 const 3 inf=123456789012345; 4 type 5 etype=record 6 t,c,next,rev:longint; 7 w:int64; 8 end; 9 var 10 e:array[0..400040]of etype; 11 a,frv,fre:array[-440..440]of longint; 12 inq:array[-440..440]of boolean; 13 dis:array[-440..440]of int64; 14 q:array[0..1000]of longint; 15 nl,nr,m,i,x,y,cnt,j,h,t:longint; 16 ans,w,f:int64; 17 function min(a,b:longint):longint; 18 begin 19 if a<b then exit(a) else exit(b); 20 end; 21 procedure ins(x,y,c:longint;w:int64); 22 begin 23 inc(cnt);e[cnt].t:=y;e[cnt].c:=c;e[cnt].w:=w;e[cnt].next:=a[x];a[x]:=cnt; 24 end; 25 procedure add(x,y,c:longint;w:int64); 26 begin 27 ins(x,y,c,w);e[cnt].rev:=cnt+1;ins(y,x,0,-w);e[cnt].rev:=cnt-1; 28 end; 29 procedure spfa; 30 begin 31 for i:=-nl to nr+1 do begin dis[i]:=-inf;inq[i]:=false; end; 32 h:=0;t:=1;q[1]:=0;dis[0]:=0;inq[0]:=true; 33 while h<>t do 34 begin 35 inc(h);if h>1000 then h:=1; 36 i:=a[q[h]]; 37 while i<>0 do 38 begin 39 if (e[i].c>0) and (dis[q[h]]+e[i].w>dis[e[i].t]) then 40 begin 41 dis[e[i].t]:=dis[q[h]]+e[i].w; 42 fre[e[i].t]:=i;frv[e[i].t]:=q[h]; 43 if not inq[e[i].t] then 44 begin 45 inc(t);if t>1000 then t:=1; 46 q[t]:=e[i].t;inq[e[i].t]:=true; 47 end; 48 end; 49 i:=e[i].next; 50 end; 51 inq[q[h]]:=false; 52 end; 53 end; 54 begin 55 assign(input,'r.in');assign(output,'r.out');reset(input);rewrite(output); 56 readln(nl,nr,m); 57 fillchar(a,sizeof(a),0);cnt:=0; 58 for i:=1 to nl do add(0,-i,1,0); 59 for i:=1 to nr do add(i,nr+1,1,0); 60 for i:=1 to m do begin readln(x,y,w);add(-x,y,1,w); end; 61 ans:=0; 62 while true do 63 begin 64 spfa; 65 if dis[nr+1]<=0 then break; 66 i:=nr+1;f:=1000;w:=0; 67 while i<>0 do begin f:=min(f,e[fre[i]].c);i:=frv[i]; end; 68 ans:=ans+dis[nr+1]*f; 69 i:=nr+1;while i<>0 do begin dec(e[fre[i]].c,f);inc(e[e[fre[i]].rev].c,f);i:=frv[i]; end; 70 end; 71 writeln(ans); 72 for i:=1 to nl do 73 begin 74 j:=a[-i]; 75 while j<>0 do begin if e[j].c=0 then break;j:=e[j].next; end; 76 if j=0 then write(0,' ') else write(e[j].t,' '); 77 end; 78 close(input);close(output); 79 end.