二分图最大权匹配模板(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。保证 1vnl1≤v≤nl,1unr1≤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,1w109

时间限制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.

 

posted @ 2017-04-12 23:55  Klaier  阅读(353)  评论(0编辑  收藏  举报