• 【HDOJ4322】Candy(费用流)


    题意:给N个孩子分配M个糖果。

    有一个N*M的矩阵表示孩子和糖果的关系,若第i行第j列的数是1则表示第i个孩子喜欢第j个糖果,反之不喜欢。

    已知,若一个孩子被分配到他喜欢的糖果那么他将获得K的快乐值,反之只能获取1的快乐值

    现在给你这N个孩子需要满足的快乐值,问你能不能满足所有孩子的需求。

    1<=N<=13, 1<=M<=13, 2<=K<=10

    0<=B[i]<=1000

    思路:RYZ作业

    费用流(经典?)模型之一

    这题的建模是使用最大费用最大流将各人喜欢的糖果作用最大化

    From:http://blog.csdn.net/chenzhenyu123456/article/details/48130365

    建图:设置超级源点source,超级汇点sink,用a表示当前孩子需要满足的快乐值

    1,source向每个糖果建边,容量1,费用0;

    2,只考虑有特殊的糖,那么对于第i个人喜欢j糖果,则j糖果向第i个人建边,容量为1,费用为0;

    3,每个孩子向汇点建边。这时需要分类讨论 

         (1) a % K == 0,表示该孩子选择(a / K)个他喜欢的糖果就可以满足,而且该孩子选择1个他喜欢的糖果,会获取K的快乐值。 建边信息——容量为(a / K),费用为K;

         (2) a % K != 0,表示该孩子选择(a / K + 1)个他喜欢的糖果才能满足,这时我们不能只建一条容量为(a / K + 1),费用为K的边,如果这样处理我们就放大了最大流时费用的最大效益。

                                 因此我们要建一条容量为(a / K),费用为K的边,再建一条容量为1,费用为a % K的边。这样的话在用特殊糖果满足该孩子的需求时,才不会使最后流入汇点的费用增加

    建好图,跑一次最大费用最大流。

    最终结果:(用sumflow记录所有孩子需要满足的快乐值之和)

    最大费用cost——特殊的糖被充分利用后所分配的快乐值之和。若cost >= sumflow 则表示已经满足条件。

    最大流flow——为了达到这样的程度使用的糖的数量。

    这样就还剩M - flow数目的糖被我们当做普通的糖使用,只要M - flow >= sumflow - cost,就可以满足条件。

      1 var head,vet,next,len1,len2,fan,dis:array[1..2000]of longint;
      2     inq:array[1..2000]of boolean;
      3     q,b:array[0..2000]of longint;
      4     a:array[1..20,1..20]of longint;
      5     pre:array[1..2000,1..2]of longint;
      6     n,m,sum,ans1,ans2,tot,source,src,s,cas,v,i,j,k: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 
     17  inc(tot);
     18  next[tot]:=head[b];
     19  vet[tot]:=a;
     20  len1[tot]:=0;
     21  len2[tot]:=-d;
     22  head[b]:=tot;
     23 end;
     24 
     25 function min(x,y:longint):longint;
     26 begin
     27  if x<y then exit(x);
     28  exit(y);
     29 end;
     30 
     31 function spfa:boolean;
     32 var u,e,v,t,w,i:longint;
     33 begin
     34  for i:=1 to s do
     35  begin
     36   dis[i]:=-(maxlongint>>1);
     37   inq[i]:=false;
     38  end;
     39  t:=0; w:=1; q[1]:=source; dis[source]:=0; inq[source]:=true;
     40  while t<w do
     41  begin
     42   inc(t); u:=q[t mod 100]; 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     dis[v]:=dis[u]+len2[e];
     50     pre[v,1]:=u;
     51     pre[v,2]:=e;
     52     if not inq[v] then
     53     begin
     54      inc(w); q[w mod 100]:=v; inq[v]:=true;
     55     end;
     56    end;
     57    e:=next[e];
     58   end;
     59  end;
     60  if dis[src]=-(maxlongint>>1) then exit(false);
     61  exit(true);
     62 end;
     63 
     64 procedure mcf;
     65 var k,e,t:longint;
     66 begin
     67  k:=src; t:=maxlongint;
     68  while k<>source do
     69  begin
     70   t:=min(t,len1[pre[k,2]]);
     71   k:=pre[k,1];
     72  end;
     73  k:=src;
     74  while k<>source do
     75  begin
     76   e:=pre[k,2];
     77   len1[e]:=len1[e]-t;
     78   len1[fan[e]]:=len1[fan[e]]+t;
     79   ans2:=ans2+t*len2[e];
     80   k:=pre[k,1];
     81  end;
     82  ans1:=ans1+t;
     83 end;
     84 
     85 begin
     86  assign(input,'hdoj4322.in'); reset(input);
     87  assign(output,'hdoj4322.out'); rewrite(output);
     88  readln(cas);
     89  for i:=1 to 2000 do
     90   if i and 1=1 then fan[i]:=i+1
     91    else fan[i]:=i-1;
     92  for v:=1 to cas do
     93  begin
     94   readln(n,m,k);
     95   for i:=1 to s do head[i]:=0;
     96   tot:=0; s:=0; ans1:=0; ans2:=0; sum:=0;
     97   for i:=1 to m do
     98   begin
     99    read(b[i]);
    100    sum:=sum+b[i];
    101   end;
    102   for i:=1 to m do
    103    for j:=1 to n do read(a[i,j]);
    104   source:=n+m+1; src:=n+m+2; s:=n+m+2;
    105   for i:=1 to n do add(source,i,1,0);
    106   for i:=1 to m do
    107    for j:=1 to n do
    108     if a[i,j]=1 then add(j,i+n,1,0);
    109   for i:=1 to m do
    110   begin
    111    add(i+n,src,b[i] div k,k);
    112    if b[i] mod k>0 then add(i+n,src,1,b[i] mod k);
    113   end;
    114   while spfa do mcf;
    115   if n-ans1>=sum-ans2 then writeln('Case #',v,': YES')
    116    else writeln('Case #',v,': NO');
    117  end;
    118  close(input);
    119  close(output);
    120 end.
  • 相关阅读:
    python_3 装饰器之初次见面
    python_迭代器
    Python_1生成器(下)之单线并行--生产着消费者模型
    Python_ 1生成器(上)初识生成器
    memcache 和 redis 的区别
    Linux 面试总结
    网络面试总结
    操作系统相关面试总结
    剑指offer 数组中的重复数字
    svn-主副分支使用
  • 原文地址:https://www.cnblogs.com/myx12345/p/6509880.html
Copyright © 2020-2023  润新知