【BZOJ4514】数字配对(费用流)
题意:
有 n 种数字,第 i 种数字是 ai、有 bi 个,权值是 ci。
若两个数字 ai、aj 满足,ai 是 aj 的倍数,且 ai/aj 是一个质数,
那么这两个数字可以配对,并获得 ci×cj 的价值。
一个数字只能参与一次配对,可以不参与配对。
在获得的价值总和不小于 0 的前提下,求最多进行多少次配对。
n≤200,ai≤10^9,bi≤10^5,∣ci∣≤10^5
思路:裸的费用流,LYY一年前就已AC
加边的时候INT64没用,WA了好久……
费用流中每次找出的最长(短)路显然是依次不增(减)的,所以当找到一次不足以增广所有边时计算最多能增加的流量,且终止
1 const oo=1<<60; 2 var head,vet,next,q,a,b,c,flag,prime,fan,f:array[1..200000]of longint; 3 pre:array[1..1000,1..2]of longint; 4 inq:array[1..1000]of boolean; 5 dis,len1,len2:array[1..200000]of int64; 6 n,m,i,tot,j,x,source,src,s,t:longint; 7 ans,flow,flow1:int64; 8 p:boolean; 9 10 function min(x,y:int64):int64; 11 begin 12 if x<y then exit(x); 13 exit(y); 14 end; 15 16 function max(x,y:int64):int64; 17 begin 18 if x>y then exit(x); 19 exit(y); 20 end; 21 22 procedure add(a,b:longint;c,d:int64); 23 begin 24 inc(tot); 25 next[tot]:=head[a]; 26 vet[tot]:=b; 27 len1[tot]:=c; 28 len2[tot]:=d; 29 head[a]:=tot; 30 31 inc(tot); 32 next[tot]:=head[b]; 33 vet[tot]:=a; 34 len1[tot]:=0; 35 len2[tot]:=-d; 36 head[b]:=tot; 37 end; 38 39 function spfa:boolean; 40 var u,e,v,i,t,w,t1,w1:longint; 41 begin 42 for i:=1 to s do 43 begin 44 dis[i]:=-oo; 45 inq[i]:=false; 46 end; 47 t:=0; t1:=0; w:=1; w1:=1; dis[source]:=0; q[1]:=source; inq[source]:=true; 48 while t<w do 49 begin 50 inc(t); inc(t1); 51 if t1=1000 then t1:=1; 52 u:=q[t1]; inq[u]:=false; 53 e:=head[u]; 54 while e<>0 do 55 begin 56 v:=vet[e]; 57 if (len1[e]>0)and(dis[u]+len2[e]>dis[v]) then 58 begin 59 pre[v,1]:=u; pre[v,2]:=e; 60 dis[v]:=dis[u]+len2[e]; 61 if not inq[v] then 62 begin 63 inc(w); inc(w1); 64 if w1=1000 then w1:=1; 65 q[w1]:=v; inq[v]:=true; 66 end; 67 end; 68 e:=next[e]; 69 end; 70 end; 71 if dis[src]=-oo then exit(false); 72 exit(true); 73 end; 74 75 procedure mcf; 76 var k,e:longint; 77 t,s,now,i:int64; 78 begin 79 t:=oo; k:=src; s:=0; 80 while k<>source do 81 begin 82 e:=pre[k,2]; 83 t:=min(t,len1[e]); 84 s:=s+len2[e]; 85 k:=pre[k,1]; 86 end; 87 88 if ans+t*s<0 then 89 begin 90 p:=false; 91 t:=ans div (-s); 92 end; 93 k:=src; 94 while k<>source do 95 begin 96 e:=pre[k,2]; 97 len1[e]:=len1[e]-t; 98 len1[fan[e]]:=len1[fan[e]]+t; 99 k:=pre[k,1]; 100 end; 101 ans:=ans+t*s; 102 flow:=flow+t; 103 104 end; 105 106 begin 107 assign(input,'bzoj4514.in'); reset(input); 108 assign(output,'bzoj4514.out'); rewrite(output); 109 readln(n); 110 for i:=1 to 200000 do 111 if i and 1=1 then fan[i]:=i+1 112 else fan[i]:=i-1; 113 for i:=1 to n do read(a[i]); 114 for i:=1 to n do read(b[i]); 115 for i:=1 to n do read(c[i]); 116 for i:=2 to 50000 do 117 begin 118 if flag[i]=0 then 119 begin 120 inc(m); prime[m]:=i; 121 end; 122 j:=1; 123 while (j<=m)and(prime[j]*i<=50000) do 124 begin 125 t:=prime[j]*i; flag[t]:=1; 126 if i mod prime[j]=0 then break; 127 inc(j); 128 end; 129 end; 130 for i:=1 to n do 131 begin 132 x:=a[i]; f[i]:=0; 133 j:=1; 134 while (x>1)and(j<=m) do 135 begin 136 while x mod prime[j]=0 do 137 begin 138 inc(f[i]); 139 x:=x div prime[j]; 140 end; 141 inc(j); 142 end; 143 if x>1 then f[i]:=1; 144 end; 145 source:=n+1; src:=n+2; s:=n+2; 146 for i:=1 to n do 147 if f[i] and 1=1 then add(source,i,b[i],0) 148 else add(i,src,b[i],0); 149 for i:=1 to n do 150 for j:=1 to n do 151 if (f[i]=f[j]+1)and(a[i] mod a[j]=0) then 152 begin 153 if f[i] and 1=1 then add(i,j,maxlongint,int64(c[i])*c[j]) 154 else add(j,i,maxlongint,int64(c[i])*c[j]); 155 end; 156 ans:=0; flow:=0; p:=true; 157 while spfa and p do mcf; 158 writeln(flow); 159 close(input); 160 close(output); 161 end.
null