【Tyvj1982】武器分配(费用流)

题意:有N个人要从A个物品中各取一个,B个物品中各取一个,选取第i个A类物品和第j个B类物品的费用是(a[i]-b[j])^2

求最小总花费

n<=a,b<=80 a[i],b[i]<=10000

思路:第一题费用流

由源点到每个A类物品连容量为1,费用为0的边

每个B类物品到第一个汇点连容量为1,费用为0的边

对于ai和bj连容量为1,费用为(a[i]-b[j])^2的边

因为只需要N对物品,由第一个汇点到第二个汇点连容量为N,费用为0的边来限制流量上限

答案就是从源点到第二个汇点流量为N的最小费用

跑SPFA费用流即可

PS:其实这道根据排序不等式是个DP,排序后做即可 但是谁叫你数据太小呢

  1 var q:array[0..300]of longint;
  2     head,vet,next,len1,len2,dis,fan:array[1..200000]of longint;
  3     pre:array[1..300,1..2]of longint;
  4     c,d:array[1..300]of longint;
  5     inq:array[1..300]of boolean;
  6     n,m,i,source,src,tot,ans,a,b,j:longint;
  7 
  8 procedure add(a,b,c,d:longint);
  9 begin
 10  inc(tot);
 11  next[tot]:=head[a];
 12  vet[tot]:=b;
 13  len1[tot]:=c;
 14  len2[tot]:=d;
 15  head[a]:=tot;
 16  inc(tot);
 17  next[tot]:=head[b];
 18  vet[tot]:=a;
 19  len1[tot]:=0;
 20  len2[tot]:=-d;
 21  head[b]:=tot;
 22 end;
 23 
 24 function min(x,y:longint):longint;
 25 begin
 26  if x<y then exit(x);
 27  exit(y);
 28 end;
 29 
 30 function spfa:boolean;
 31 var t,u,e,v,i,w:longint;
 32 begin
 33  for i:=1 to 202 do
 34  begin
 35   dis[i]:=maxlongint div 2;
 36   inq[i]:=false;
 37  end;
 38  t:=-1; w:=0; q[0]:=source; inq[source]:=true; dis[source]:=0;
 39  while t<w do
 40  begin
 41   inc(t); u:=q[t mod 300];
 42   inq[u]:=false;
 43   e:=head[u];
 44   while e<>0 do
 45   begin
 46    v:=vet[e];
 47    if (len1[e]>0)and(dis[u]+len2[e]<dis[v]) then
 48    begin
 49     pre[v,1]:=u;
 50     pre[v,2]:=e;
 51     dis[v]:=dis[u]+len2[e];
 52     if not inq[v] then
 53     begin
 54      inc(w); q[w mod 300]:=v;
 55      inq[v]:=true;
 56     end;
 57    end;
 58    e:=next[e];
 59   end;
 60  end;
 61  if dis[src]=maxlongint div 2 then exit(false)
 62   else exit(true);
 63 end;
 64 
 65 procedure mcf;
 66 var k,t,e:longint;
 67 begin
 68  k:=src; t:=maxlongint;
 69  while k<>source do
 70  begin
 71   t:=min(t,len1[pre[k,2]]);
 72   k:=pre[k,1];
 73  end;
 74  k:=src;
 75  while k<>source do
 76  begin
 77   e:=pre[k,2];
 78   len1[e]:=len1[e]-t;
 79   len1[fan[e]]:=len1[fan[e]]+t;
 80   ans:=ans+t*len2[e];
 81   k:=pre[k,1];
 82  end;
 83 end;
 84 
 85 begin
 86  assign(input,'tyvj1982.in'); reset(input);
 87  assign(output,'tyvj1982.out'); rewrite(output);
 88  readln(n,a,b);
 89  for i:=1 to 200000 do
 90   if i mod 2=1 then fan[i]:=i+1
 91    else fan[i]:=i-1;
 92  for i:=1 to a do read(c[i]);
 93  for i:=1 to b do read(d[i]);
 94  for i:=1 to a do
 95   for j:=1 to b do add(i,a+j,1,(c[i]-d[j])*(c[i]-d[j]));
 96  source:=200; src:=202;
 97  for i:=1 to a do add(source,i,1,0);
 98  for i:=1 to b do add(i+a,201,1,0);
 99  add(201,src,n,0);
100  while spfa do mcf;
101  writeln(ans);
102  close(input);
103  close(output);
104 end.
原文地址:https://www.cnblogs.com/myx12345/p/6194603.html