• 一类最小割bzoj2127,bzoj2132 bzoj3438


    思考一下我们接触的最小割问题

    1. 最小割的基本问题(可能会和图论的知识相结合,比如bzoj1266,bzoj1797)

    2. 最大权闭合图(bzoj1497)

    3. 最大点权覆盖集,最大点权独立集(bzoj1324)

    最近接触到了一类关于最小割新的问题,我也不知道叫什么好

    反正它有这么几个特点

    1. 每个点都有两种选择的可能性,设为属于S和属于T,属于S有收益a[i],属于T有收益b[i]

    2. 两点之间可能因为同在一个或不在同一个集合内产生额外的收益

    3. 使收益最大化(废话)

    大概就是这个意思,如果看不懂也没关系,我们先从最简单的问题开始分析

    首先在满足1的条件下,我们有m对关系,点i和j若同在一个集合,那么就能产生一个额外收益w[i,j];

    最终使收益最大化。

    对此,我们对于每个点i,我们连s--->i 流量为a[i], i--->t 流量为b[i];

    然后对于每对关系(i,j),连i<---j,j--->i 流量都为w[i,j];

    然后怎么做呢?根据割的定义,就是s到t没有路

    在这里就是,割完之后每个点要么和s连,要么和t连;

    我们假如以两个点的图为例,思考一下最小割可能割掉的边(我比较懒,就不发图了)

    就会发现,这里的最小割正能使不在一个集合的两个点之间的边被切断

    或者使在一个集合的两个点之间的边不被切断

    最终ans=∑a[i]+∑b[i]+∑w[i,j]-mincut

    这里割对应一种解决问题的方案

    好这是最初步,下面就是bzoj2132的问题,

    条件2变成了,不在同一个集合里的两点会产生一个额外的收益

    我们先按基本问题的方式建图

    有了最开始的经验,我们不难猜测,

    假如选择一个点集,使其中的点i,颠倒一下使s-->i的流量为b[i],i-->t的流量为a[i];

    这样我们再做最小割,不就又变回了最基本的问题吗?

    而我们应该怎么选择点集呢?

    显然,这个点集内部的点是不能有关系的,并且,这些点是给出关系中一侧的点;

    说的明确一点,就是不管S,T,根据关系建得的图G,必须是一个二分图;

    那么这道题满不满足呢?

    我们对平面图黑白相间染色,显然黑点与白点才会产生关系,

    黑点与黑点,白点与白点之间是没有关系——是二分图!

    于是这道题就简单了!

     1 const dx:array[1..4] of integer=(0,0,1,-1);
     2       dy:array[1..4] of integer=(1,-1,0,0);
     3       inf=100000007;
     4 
     5 type node=record
     6        point,next,flow:longint;
     7      end;
     8 
     9 var edge:array[0..200010] of node;
    10     p,cur,h,numh,pre:array[0..10010] of longint;
    11     c,num:array[0..110,0..110] of longint;
    12     s,x,y,i,j,k,n,m,len,t:longint;
    13 
    14 procedure add(x,y,f:longint);
    15   begin
    16     inc(len);
    17     edge[len].flow:=f;
    18     edge[len].point:=y;
    19     edge[len].next:=p[x];
    20     p[x]:=len;
    21   end;
    22 
    23 begin
    24   len:=-1;
    25   fillchar(p,sizeof(p),255);
    26   readln(n,m);
    27   t:=n*m+1;
    28   for i:=1 to n do
    29     for j:=1 to m do
    30     begin
    31       inc(k);
    32       num[i,j]:=k;
    33       read(x);
    34       s:=s+x;
    35       if (i+j) mod 2=1 then   //黑白染色
    36       begin
    37         add(0,k,x);
    38         add(k,0,x);
    39       end
    40       else begin
    41         add(k,t,x);
    42         add(t,k,0);
    43       end;
    44     end;
    45 
    46   for i:=1 to n do
    47     for j:=1 to m do
    48     begin
    49       read(x);
    50       s:=s+x;
    51       if (i+j) mod 2=1 then
    52       begin
    53         add(num[i,j],t,x);
    54         add(t,num[i,j],x);
    55       end
    56       else begin
    57         add(0,num[i,j],x);
    58         add(num[i,j],0,0);
    59       end;
    60     end;
    61   for i:=1 to n do
    62     for j:=1 to m do
    63       read(c[i,j]);
    64   for i:=1 to n do
    65     for j:=1 to m do
    66       for k:=1 to 4 do
    67       begin
    68         x:=i+dx[k];
    69         y:=j+dy[k];
    70         if num[x,y]>0 then
    71         begin
    72           s:=s+c[i,j];
    73           add(num[i,j],num[x,y],c[i,j]+c[x,y]);  //两地建筑物类型不同,增加的额外收益是相互的,一荣俱荣一损俱损
    74           add(num[x,y],num[i,j],0);
    75         end;
    76       end;
    77   writeln(s-sap);  //求最大流省略
    78 end.
    2132

    下面再扩展这个问题

    条件2变为若点i,j同属于S,增加额外收益为w[i,j],

    若点i,j同属于T,增加额外收益为r[i,j];  (这就是bzoj2127)

    我们对于每个点i,我们连s--->i 流量为a[i], i--->t 流量为b[i];

    显然,之前根据关系的建图方法已经不适用了,我们要思考怎么解决同属于S,同属于T所带来的收益

    这必须得回到割的意义上来,我们知道割表示损失,我们取不到的

    那我们就来分析一下损失:

    1. 当i和j同时属于S的时候,我们损失了r[i,j]

    2. 当i和j同时属于T的时候,我们损失了w[i,j]

    3. 当i,j属于不同的集合,我们损失了w[i,j]+r[i,j]

    这有什么用呢?我们可以换一种方式表达

    当i属于S时,损失了r[i,j]/2,当j属于S时,损失了r[i,j]/2

    当i属于T时,损失了w[i,j]/2,当j属于T时,损失了w[i,j]/2

    这样我们再看3,我们还要在增加(w[i,j]+r[i,j])/2的损失

    不难发现,问题又变回了最基本的问题

    对于点i,我们增加s--->i 流量为r[i,j]/2,t--->i 流量为w[i,j]/2

    对于每对关系(i,j),连i<---j,j--->i 流量都为(w[i,j]+r[i,j])/2;

    ans=所有可能收益和-mincut

    为了方便,我们可以一开始把流量全乘2,最后再除以2即可

    友情提示:这道题不加当前弧优化的sap会TLE

      1 const inf=1000000007;
      2       dx:array[1..4] of integer=(-1,1,0,0);
      3       dy:array[1..4] of integer=(0,0,-1,1);
      4 
      5 type node=record
      6        point,next,flow:longint;
      7      end;
      8 
      9 var edge:array[0..500010] of node;
     10     d,p,cur,h,numh,pre:array[0..10010] of longint;
     11     a:array[0..110,0..110,1..4] of longint;
     12     num,b,c:array[0..110,0..110] of longint;
     13     n,m,t,s,x,i,j,k,len,y:longint;
     14 
     15 function min(a,b:longint):longint;
     16   begin
     17     if a>b then exit(b) else exit(a);
     18   end;
     19 
     20 procedure add(x,y,f:longint);
     21   begin
     22     inc(len);
     23     edge[len].point:=y;
     24     edge[len].flow:=f;
     25     edge[len].next:=p[x];
     26     p[x]:=len;
     27   end;
     28 
     29 function sap:longint;
     30   var tmp,neck,u,i,j,q:longint;
     31       flag:boolean;
     32 
     33   begin
     34     numh[0]:=t+1;
     35     u:=0;
     36     sap:=0;
     37     cur:=p;
     38     neck:=inf;
     39     while h[0]<t do
     40     begin
     41       d[u]:=neck;
     42       flag:=false;
     43       i:=cur[u];
     44       while i<>-1 do
     45       begin
     46         j:=edge[i].point;
     47         if (edge[i].flow>0) and (h[u]=h[j]+1) then
     48         begin
     49           flag:=true;
     50           neck:=min(neck,edge[i].flow);
     51           cur[u]:=i;
     52           pre[j]:=u;
     53           u:=j;
     54           if u=t then
     55           begin
     56             sap:=sap+neck;
     57             i:=t;
     58             while i<>0 do
     59             begin
     60               i:=pre[i];
     61               j:=cur[i];
     62               dec(edge[j].flow,neck);
     63               inc(edge[j xor 1].flow,neck);
     64             end;
     65             neck:=inf;
     66             u:=0;
     67           end;
     68           break;
     69         end;
     70         i:=edge[i].next;
     71       end;
     72       if not flag then
     73       begin
     74         dec(numh[h[u]]);
     75         if numh[h[u]]=0 then exit;
     76         tmp:=t;
     77         i:=p[u];
     78         q:=0;
     79         while i<>-1 do
     80         begin
     81           j:=edge[i].point;
     82           if (edge[i].flow>0) and (h[j]<tmp) then
     83           begin
     84             q:=i;
     85             tmp:=h[j];
     86           end;
     87           i:=edge[i].next;
     88         end;
     89         cur[u]:=q;
     90         h[u]:=tmp+1;
     91         inc(numh[h[u]]);
     92         if u<>0 then
     93         begin
     94           u:=pre[u];
     95           neck:=d[u];
     96         end;
     97       end;
     98     end;
     99   end;
    100 
    101 begin
    102   readln(n,m);
    103   len:=-1;
    104   fillchar(p,sizeof(p),255);
    105   t:=n*m+1;
    106   for i:=1 to n do
    107   begin
    108     for j:=1 to m do
    109     begin
    110       inc(k);
    111       num[i,j]:=k;
    112       read(x);
    113       s:=s+x;
    114       x:=x shl 1;
    115       b[i,j]:=b[i,j]+x;
    116     end;
    117     readln;
    118   end;
    119   for i:=1 to n do
    120   begin
    121     for j:=1 to m do
    122     begin
    123       read(x);
    124       s:=s+x;
    125       x:=x shl 1;
    126       c[i,j]:=c[i,j]+x;
    127     end;
    128     readln;
    129   end;
    130 
    131   for i:=1 to n-1 do
    132   begin
    133     for j:=1 to m do
    134     begin
    135       read(x);
    136       s:=s+x;
    137       b[i,j]:=b[i,j]+x;
    138       b[i+1,j]:=b[i+1,j]+x;
    139       a[i,j,2]:=a[i,j,2]+x;
    140       a[i+1,j,1]:=a[i+1,j,1]+x;
    141     end;
    142     readln;
    143   end;
    144 
    145   for i:=1 to n-1 do
    146   begin
    147     for j:=1 to m do
    148     begin
    149       read(x);
    150       s:=s+x;
    151       c[i,j]:=c[i,j]+x;
    152       c[i+1,j]:=c[i+1,j]+x;
    153       a[i,j,2]:=a[i,j,2]+x;
    154       a[i+1,j,1]:=a[i+1,j,1]+x;
    155     end;
    156     readln;
    157   end;
    158 
    159   for i:=1 to n do
    160   begin
    161     for j:=1 to m-1 do
    162     begin
    163       read(x);
    164       s:=s+x;
    165       b[i,j]:=b[i,j]+x;
    166       b[i,j+1]:=b[i,j+1]+x;
    167       a[i,j,4]:=a[i,j,4]+x;
    168       a[i,j+1,3]:=a[i,j+1,3]+x;
    169     end;
    170     readln;
    171   end;
    172 
    173   for i:=1 to n do
    174   begin
    175     for j:=1 to m-1 do
    176     begin
    177       read(x);
    178       s:=s+x;
    179       c[i,j]:=c[i,j]+x;
    180       c[i,j+1]:=c[i,j+1]+x;
    181       a[i,j,4]:=a[i,j,4]+x;
    182       a[i,j+1,3]:=a[i,j+1,3]+x;
    183     end;
    184     readln;
    185   end;
    186   for i:=1 to n do
    187     for j:=1 to m do
    188     begin
    189       for k:=1 to 4 do
    190       begin
    191         x:=i+dx[k];
    192         y:=j+dy[k];
    193         if num[x,y]>0 then
    194         begin
    195           add(num[i,j],num[x,y],a[i,j,k]); //注意序号的对应
    196           add(num[x,y],num[i,j],0);
    197         end;
    198       end;
    199       add(0,num[i,j],b[i,j]);
    200       add(num[i,j],0,0);
    201       add(num[i,j],t,c[i,j]);
    202       add(t,num[i,j],0);
    203     end;
    204   writeln(s-sap div 2);
    205 end.
    2127

    这个问题最终阶段是bzoj3438 不再是两点间关系而是多点间关系了

    即多个点如果同属A集合会产生一个额外收益c1,同属于B集合会产生一个额外收益c2

    这就不能用上述的做法了,具体做法见bzoj3438的解题报告

  • 相关阅读:
    (转)MP4文件两种格式AVC1和H264的区别及利用FFMPEG demux为h264码流事项
    (转)【多媒体封装格式详解】--- AAC ADTS格式分析
    (转)使用FFMPEG类库分离出多媒体文件中的H.264码流
    (转)ffmpeg 从mp4上提取H264的nalu
    (原)hisi3531立体声pcm实现播放方式
    (转)关于yuv 格式:planar和semi-planar格式
    (转)LCD:LCD常用接口原理篇
    Instrumentation 两种方法 premain Agent
    解决-Dmaven.multiModuleProjectDirectory system property is not set. Check $M2_HOME environment variabl
    Java反射机制获取Class文件
  • 原文地址:https://www.cnblogs.com/phile/p/4473226.html
Copyright © 2020-2023  润新知