• 【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.
  • 相关阅读:
    Java NIO开发需要注意的陷阱(转)
    Java Nio注意事项
    NIO的介绍及使用(总结)
    蓝萝卜blu netty3升netty4
    tcp nio 远程主机强迫关闭了一个现有的连接
    java 竖线分割字符串的问题
    15个免费好用的抓包工具
    JSP 基础之 JSTL <c:forEach>用法
    JSP中多条件判断
    怎么不让控制台system.out.println()打印
  • 原文地址:https://www.cnblogs.com/myx12345/p/6749032.html
Copyright © 2020-2023  润新知