二分图最大权匹配模板(pascal)

用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,但我不会啦。

 program rrr(input,output);
const
inf=;
type
etype=record
t,c,next,rev:longint;
w:int64;
end;
var
e:array[..]of etype;
a,frv,fre:array[-..]of longint;
inq:array[-..]of boolean;
dis:array[-..]of int64;
q:array[..]of longint;
nl,nr,m,i,x,y,cnt,j,h,t:longint;
ans,w,f:int64;
function min(a,b:longint):longint;
begin
if a<b then exit(a) else exit(b);
end;
procedure ins(x,y,c:longint;w:int64);
begin
inc(cnt);e[cnt].t:=y;e[cnt].c:=c;e[cnt].w:=w;e[cnt].next:=a[x];a[x]:=cnt;
end;
procedure add(x,y,c:longint;w:int64);
begin
ins(x,y,c,w);e[cnt].rev:=cnt+;ins(y,x,,-w);e[cnt].rev:=cnt-;
end;
procedure spfa;
begin
for i:=-nl to nr+ do begin dis[i]:=-inf;inq[i]:=false; end;
h:=;t:=;q[]:=;dis[]:=;inq[]:=true;
while h<>t do
begin
inc(h);if h> then h:=;
i:=a[q[h]];
while i<> do
begin
if (e[i].c>) and (dis[q[h]]+e[i].w>dis[e[i].t]) then
begin
dis[e[i].t]:=dis[q[h]]+e[i].w;
fre[e[i].t]:=i;frv[e[i].t]:=q[h];
if not inq[e[i].t] then
begin
inc(t);if t> then t:=;
q[t]:=e[i].t;inq[e[i].t]:=true;
end;
end;
i:=e[i].next;
end;
inq[q[h]]:=false;
end;
end;
begin
assign(input,'r.in');assign(output,'r.out');reset(input);rewrite(output);
readln(nl,nr,m);
fillchar(a,sizeof(a),);cnt:=;
for i:= to nl do add(,-i,,);
for i:= to nr do add(i,nr+,,);
for i:= to m do begin readln(x,y,w);add(-x,y,,w); end;
ans:=;
while true do
begin
spfa;
if dis[nr+]<= then break;
i:=nr+;f:=;w:=;
while i<> do begin f:=min(f,e[fre[i]].c);i:=frv[i]; end;
ans:=ans+dis[nr+]*f;
i:=nr+;while i<> do begin dec(e[fre[i]].c,f);inc(e[e[fre[i]].rev].c,f);i:=frv[i]; end;
end;
writeln(ans);
for i:= to nl do
begin
j:=a[-i];
while j<> do begin if e[j].c= then break;j:=e[j].next; end;
if j= then write(,' ') else write(e[j].t,' ');
end;
close(input);close(output);
end.
上一篇:unlocker208安装之后看不到Apple macos选项,解决办法.


下一篇:PHP程序员函数注释规格