• 【PowerOJ1740&网络流24题】圆桌聚餐(最大流)


    题意:

    来自n个不同国家的代表开会,每个国家代表数为ci 会场有m张圆桌,每张桌子可容纳mi人 不希望有同一个国家的代表在同一张桌子上就餐 设计一个合法方案

    (n,m<=300)

    思路:最大流,保存原边上限,与残余网络比较是否有所变动即可。

    【问题分析】

    二分图多重匹配问题,可以用最大流解决。

    【建模方法】

    建立二分图,每个单位为X集合中的顶点,每个餐桌为Y集合中的顶点,增设附加源S和汇T。

    1、从S向每个Xi顶点连接一条容量为该单位人数的有向边。

    2、从每个Yi顶点向T连接一条容量为该餐桌容量的有向边。

    3、X集合中每个顶点向Y集合中每个顶点连接一条容量为1的有向边。

    求网络最大流,如果最大流量等于所有单位人数之和,则存在解,否则无解。对于每个单位,从X集合对应点出发的所有满流边指向的Y集合的顶点就是该单位人员的安排情况(一个可行解)。

    【建模分析】

    对于一个二分图,每个顶点可以有多个匹配顶点,称这类问题为二分图多重匹配问题。X,Y集合之间的边容量全部是1,保证两个点只能匹配一次(一个餐桌上只能有一个单位的一个人),源汇的连边限

    制了每个点匹配的个数。求出网络最大流,如果流量等于X集合所有点与S边容量之和,那么则说明X集合每个点都有完备的多重匹配。

    【问题另解】

    贪心,更好的方法其实是贪心。首先把所有单位和餐桌按人数从大到小排序,一种适当的贪心策略就是对于每个单位,所有人每次尽量去剩余容量较大的餐桌就坐。按照这种贪心策略,如果某时发现有人

    已经无法就坐,则无解。具体方法为用线段树维护餐桌的剩余容量,按人数从多到少安排每个单位的人员,每次安排就是把容量餐桌前k大的餐桌人数减1(k为该单位人数)。为保证线段树前k位时刻为前

    k大,要维护第k与第k+1,k+2,...人数与第k相等的位置,减少第k大时要减少尽量靠后的,这样才能保证单调。

    UPD(19.10.28):显然这个线段树维护的贪心做法只有在判断是否有解的时候有用,因为光输出方案的复杂度就比它大

    其次这个前k大变动的时刻真的能维护?理解不能……

    UPD(19.10.29):听说splay可以做,要支持区间-1和把前k大的区间抠出来,等其他题目结束以后写一下,感觉细节有点多

      1 var head,vet,next,len,dis,gap,ob,save,fan:array[0..300000]of longint;
      2     a,b,q:array[1..300]of longint;
      3     num:array[1..200,1..300]of longint;
      4     n,m,i,j,src,source,tot,s,sum:longint;
      5 
      6 procedure add(a,b,c:longint);
      7 begin
      8  inc(tot);
      9  next[tot]:=head[a];
     10  vet[tot]:=b;
     11  len[tot]:=c;
     12  head[a]:=tot;
     13 
     14  inc(tot);
     15  next[tot]:=head[b];
     16  vet[tot]:=a;
     17  len[tot]:=0;
     18  head[b]:=tot;
     19 end;
     20 
     21 function min(x,y:longint):longint;
     22 begin
     23  if x<y then exit(x);
     24  exit(y);
     25 end;
     26 
     27 function dfs(u,aug:longint):longint;
     28 var e,v,t,val,flow:longint;
     29 begin
     30  if u=src then exit(aug);
     31  e:=head[u]; val:=s-1; flow:=0;
     32  while e<>0 do
     33  begin
     34   v:=vet[e];
     35   if len[e]>0 then
     36   begin
     37    if dis[u]=dis[v]+1 then
     38    begin
     39     t:=dfs(v,min(len[e],aug-flow));
     40     len[e]:=len[e]-t;
     41     len[fan[e]]:=len[fan[e]]+t;
     42     flow:=flow+t;
     43     if dis[source]>=s then exit(flow);
     44     if aug=flow then break;
     45    end;
     46    val:=min(val,dis[v]);
     47   end;
     48   e:=next[e];
     49  end;
     50  if flow=0 then
     51  begin
     52   dec(gap[dis[u]]);
     53   if gap[dis[u]]=0 then dis[source]:=s;
     54   dis[u]:=val+1;
     55   inc(gap[dis[u]]);
     56  end;
     57  exit(flow);
     58 end;
     59 
     60 function maxflow:longint;
     61 var ans:longint;
     62 begin
     63  fillchar(gap,sizeof(gap),0);
     64  fillchar(dis,sizeof(dis),0);
     65  gap[0]:=s; ans:=0;
     66  while dis[source]<s do ans:=ans+dfs(source,maxlongint);
     67  exit(ans);
     68 end;
     69 
     70 procedure print;
     71 var i,j,s:longint;
     72 begin
     73  writeln(1);
     74  for i:=1 to n do
     75  begin
     76   s:=0;
     77   for j:=1 to m do
     78    if len[num[i,j]]<>save[num[i,j]] then begin inc(s); q[s]:=j; end;
     79   for j:=1 to s-1 do write(q[j],' ');
     80   write(q[s]);
     81   writeln;
     82  end;
     83 end;
     84 
     85 begin
     86  assign(input,'poweroj1740.in'); reset(input);
     87  assign(output,'poweroj1740.out'); rewrite(output);
     88  readln(n,m);
     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 n do begin read(a[i]); sum:=sum+a[i]; end;
     93  for i:=1 to m do read(b[i]);
     94  s:=n+m+2; source:=n+m+1; src:=n+m+2;
     95  for i:=1 to n do
     96   for j:=1 to m do
     97   begin
     98    num[i,j]:=tot+1; add(i,j+n,1);
     99   end;
    100  for i:=1 to tot do save[i]:=len[i];
    101  for i:=1 to n do add(source,i,a[i]);
    102  for i:=1 to m do add(i+n,src,b[i]);
    103  if maxflow<sum then writeln(0)
    104   else print;
    105  close(input);
    106  close(output);
    107 end.
  • 相关阅读:
    852. Peak Index in a Mountain Array
    841. Keys and Rooms
    832. Flipping an Image
    821. Shortest Distance to a Character
    824. Goat Latin
    如何生成git的公钥和私钥
    学习笔记
    加快JavaScript加载和执行效率
    PO BO VO DTO POJO DAO概念及其作用
    jvm 垃圾回收区的形象说明
  • 原文地址:https://www.cnblogs.com/myx12345/p/6223303.html
Copyright © 2020-2023  润新知