bzoj4514 [Sdoi2016]数字配对(网络流)
Description
有 n 种数字,第 i 种数字是 ai、有 bi 个,权值是 ci。
若两个数字 ai、aj 满足,ai 是 aj 的倍数,且 ai/aj 是一个质数,
那么这两个数字可以配对,并获得 ci×cj 的价值。
一个数字只能参与一次配对,可以不参与配对。
在获得的价值总和不小于 0 的前提下,求最多进行多少次配对。
Input
第一行一个整数 n。
第二行 n 个整数 a1、a2、……、an。
第三行 n 个整数 b1、b2、……、bn。
第四行 n 个整数 c1、c2、……、cn。
Output
一行一个数,最多进行多少次配对
Sample Input
3
2 4 8
2 200 7
-1 -2 1
2 4 8
2 200 7
-1 -2 1
Sample Output
4
HINT
n≤200,ai≤10^9,bi≤10^5,∣ci∣≤10^5
Source
鸣谢Menci上传
主要是要注意到质因数有几个(2^2算两个),这样个数为奇数只能与个数为偶数配对,个数为偶数只能和个数为奇数配对,然后就是一个二分图,随便建一建图跑最大费用流就好。
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; 26 procedure add(x,y,c:longint;w:int64); 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; 63 readln(n); 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.