bzoj4514 [Sdoi2016]数字配对（网络流）

一行一个数，最多进行多少次配对

3
2 4 8
2 200 7
-1 -2 1

4

HINT

n≤200，ai≤10^9，bi≤10^5，∣ci∣≤10^5

Source

 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..100000]of etype;
11   num,a,d,q,fre,frv:array[0..220]of longint;
12   s:array[0..100010]of boolean;
13   p:array[0..100010]of longint;
14   c,dis:array[0..220]of int64;
15   inq:array[0..220]of boolean;
16   n,m,i,j,x,b,cnt,h,t,ans:longint;
17   w,f:int64;
18 function min(a,b:int64):int64;
19 begin
20    if a<b then exit(a) else exit(b);
21 end;
22 procedure ins(x,y,c:longint;w:int64);
23 begin
24    inc(cnt);e[cnt].t:=y;e[cnt].c:=c;e[cnt].w:=w;e[cnt].next:=a[x];a[x]:=cnt;
25 end;
27 begin
28    ins(x,y,c,w);e[cnt].rev:=cnt+1;ins(y,x,0,-w);e[cnt].rev:=cnt-1;
29 end;
30 procedure spfa;
31 begin
32    for i:=1 to n do dis[i]:=-inf;dis[0]:=0;
33    h:=0;t:=1;q[1]:=0;inq[0]:=true;
34    while h<>t do
35       begin
36          inc(h);if h>210 then h:=1;
37          i:=a[q[h]];
38          while i<>0 do
39             begin
40                if (e[i].c>0) and (dis[q[h]]+e[i].w>dis[e[i].t]) then
41                   begin
42                      dis[e[i].t]:=dis[q[h]]+e[i].w;
43                      fre[e[i].t]:=i;frv[e[i].t]:=q[h];
44                      if not inq[e[i].t] then
45                         begin
46                            inc(t);if t>210 then t:=1;
47                            q[t]:=e[i].t;inq[e[i].t]:=true;
48                         end;
49                   end;
50                i:=e[i].next;
51             end;
52          inq[q[h]]:=false;
53       end;
54 end;
55 begin
56    assign(input,'r.in');assign(output,'r.out');reset(input);rewrite(output);
57    fillchar(s,sizeof(s),true);s[1]:=false;
58    for i:=2 to 320 do if s[i] then
59       begin
60          j:=i+i;while j<=100000 do begin s[j]:=false;j:=j+i; end;
61       end;
62    m:=0;for i:=2 to 100000 do if s[i] then begin inc(m);p[m]:=i; end;
64    for i:=1 to n do read(num[i]);
65    for i:=1 to n do
66       begin
67          x:=num[i];j:=1;d[i]:=0;
68          while x>1 do begin while x mod p[j]=0 do begin inc(d[i]);x:=x div p[j]; end;inc(j);if j>m then break; end;
69          if x>1 then inc(d[i]);
70       end;
71    fillchar(a,sizeof(a),0);cnt:=0;
72    for i:=1 to n do begin read(b);if d[i] mod 2=0 then add(i,n+1,b,0) else add(0,i,b,0); end;
73    for i:=1 to n do read(c[i]);
74    for i:=1 to n do for j:=i+1 to n do
75       if (abs(d[i]-d[j])=1) and ((num[i] mod num[j]=0) or (num[j] mod num[i]=0)) then
76          begin
77             if d[i] mod 2=0 then add(j,i,100000000,c[i]*c[j]) else add(i,j,100000000,c[i]*c[j]);
78          end;
79    ans:=0;inc(n);w:=0;
80    while true do
81       begin
82          spfa;
83          if dis[n]=-inf then break;
84          i:=n;f:=100000000;
85          while i<>0 do begin f:=min(f,e[fre[i]].c);i:=frv[i]; end;
86          if w+f*dis[n]<0 then begin ans:=ans+w div (-dis[n]);break; end
87          else begin ans:=ans+f;w:=w+f*dis[n]; end;
88          i:=n;while i<>0 do begin dec(e[fre[i]].c,f);inc(e[e[fre[i]].rev].c,f);i:=frv[i]; end;
89       end;
90    write(ans);
91    close(input);close(output);
92 end.

posted @ 2017-04-13 20:40  Klaier  阅读(175)  评论(0编辑  收藏  举报