【HDOJ6118】度度熊的交易计划(费用流)

题意:

度度熊参与了喵哈哈村的商业大会,但是这次商业大会遇到了一个难题:

喵哈哈村以及周围的村庄可以看做是一共由n个片区,m条公路组成的地区。

由于生产能力的区别,第i个片区能够花费a[i]元生产1个商品,但是最多生产b[i]个。

同样的,由于每个片区的购买能力的区别,第i个片区也能够以c[i]的价格出售最多d[i]个物品。

由于这些因素,度度熊觉得只有合理的调动物品,才能获得最大的利益。

据测算,每一个商品运输1公里,将会花费1元。

那么喵哈哈村最多能够实现多少盈利呢?

1<=n<=500,
1<=m<=1000,
1<=a[i],b[i],c[i],d[i],k[i]<=1000,
1<=u[i],v[i]<=n

思路:明显的一个最小费用流模型 写的是最大费用流,注意没有要求流量最大

刚开始TooNaive先跑了一波最短路然后建的图

而后发现直接照原图建边,费用流过程中就会自动调整到最短路上

还是要学习一个

SPFA找的时候如果当前继续跑流会使利润减小就停止,即dis[src]<0

  1 const inf=10000000000000000000;
  2 var q:array[0..10000]of longint;
  3     f:array[1..1000,1..1000]of longint;
  4     a,b,c,d,dis:array[1..1000]of longint;
  5     head,vet,len1,len2,next:array[1..600000]of longint;
  6     pre:array[0..10000,1..2]of longint;
  7     inq:array[0..1000]of boolean;
  8     fan:array[0..600000]of longint;
  9     n,m,i,tot,t1,s,source,src,x,y,z,j:longint;
 10     ans1,ans2:int64;
 11 
 12 
 13 procedure add(a,b,c,d:longint);
 14 begin
 15  inc(tot);
 16  next[tot]:=head[a];
 17  vet[tot]:=b;
 18  len1[tot]:=c;
 19  len2[tot]:=d;
 20  head[a]:=tot;
 21 end;
 22 
 23 function min(x,y:int64):int64;
 24 begin
 25  if x<y then min:=x
 26   else min:=y;
 27 end;
 28 
 29 function spfa:boolean;
 30 var u,e,v,t,w,i:longint;
 31 begin
 32  for i:=1 to s do
 33  begin
 34   dis[i]:=-(maxlongint>>1);
 35   inq[i]:=false;
 36  end;
 37  t:=0; w:=1; q[1]:=source; dis[source]:=0; inq[source]:=true;
 38  while t<w do
 39  begin
 40   inc(t); u:=q[t mod 10000]; inq[u]:=false;
 41   e:=head[u];
 42   while e<>0 do
 43   begin
 44    v:=vet[e];
 45    if (len1[e]>0)and(dis[u]+len2[e]>dis[v]) then
 46    begin
 47     dis[v]:=dis[u]+len2[e];
 48     pre[v,1]:=u;
 49     pre[v,2]:=e;
 50     if not inq[v] then
 51     begin
 52      inc(w); q[w mod 10000]:=v; inq[v]:=true;
 53     end;
 54    end;
 55    e:=next[e];
 56   end;
 57  end;
 58  //if dis[src]=-(maxlongint>>1) then spfa:=false
 59  // else spfa:=true;
 60  if dis[src]<0 then spfa:=false
 61   else spfa:=true;
 62 end;
 63 
 64 procedure mcf;
 65 var k,e:longint;
 66     t:int64;
 67 begin
 68  k:=src; t:=1<<55;
 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   ans2:=ans2+t*len2[e];
 81   k:=pre[k,1];
 82  end;
 83 end;
 84 
 85 begin
 86  assign(input,'1005.in'); reset(input);
 87  assign(output,'1005.out'); rewrite(output);
 88  for i:=1 to 600000 do
 89   if i and 1=1 then fan[i]:=i+1
 90    else fan[i]:=i-1;
 91  while not eof do
 92  begin
 93   read(n,m);
 94   tot:=0;
 95   if (n=0)and(m=0) then break;
 96   for i:=1 to n do read(a[i],b[i],c[i],d[i]);
 97   tot:=0;
 98   for i:=1 to n do head[i]:=0;
 99   source:=n+1; src:=n+2; s:=n+2;
100   for i:=1 to n do
101   begin
102    add(source,i,b[i],-a[i]);
103    add(i,source,0,a[i]);
104   end;
105   for i:=1 to n do
106   begin
107    add(i,src,d[i],c[i]);
108    add(src,i,0,-c[i]);
109   end;
110 
111   for i:=1 to m do
112   begin
113    read(x,y,z);
114    add(x,y,maxlongint,-z);
115    add(y,x,0,z);
116    add(y,x,maxlongint,-z);
117    add(x,y,0,z);
118   end;
119   ans1:=0; ans2:=0;
120   while spfa do mcf;
121   writeln(ans2);
122   for i:=1 to s do head[i]:=0;
123   for i:=1 to s do dis[i]:=0;
124   for i:=1 to s do
125    for j:=1 to 2 do pre[i,j]:=0;
126  end;
127  close(input);
128  close(output);
129 
130 end.
原文地址:https://www.cnblogs.com/myx12345/p/7354436.html