zoukankan      html  css  js  c++  java
  • bzoj3438

    很容易想到是最小割模型
    首先对于一个点i,从s到i连一条容量为ai的边,再从i连一条容量为bi的边到t
    然后就是处理附加权的问题了
    一开始受到之前的思维定势的影响,一直在思考怎么在作物之间连边
    由于每种额外收益对应多种作物,而不再是原来bzoj2132的二元关系最小割,这是不行的
    所以我们考虑可以把一种组合作物方式看成一个两点u,v,表示同时种在一个A、B田里的两种情况
    对于u,我们连边s-->u 容量为c1,再从u向对应每种作物连一条容量inf的边
    对于v,我们连边v-->t 容量为c2,再从对应每个作物向v连一条容量inf的边(组合方式是固定的,这些边当然不能割去)
    不难发现,做最小割后s-->u,v-->t的容量不能同时保存,
    且同时假设保留s-->u 那么对应作物与t的连边一定被割去,相当于对应作物都种在A地中
    保留v-->t同理,所以这样建图做最小割是正确的
    最终ans=所有收益-mincut

    还有种想法我觉得更好的是做最大权闭合子图
    首先我们把所有作物都种在A田地里,然后再通过调整选一些作物种在B里取得最优答案
    我们把每个额外收益看作一个点,点权为c2-c1,每个作物的点权为bi-ai;
    要选取某个作物组合改成种在B里,那么必然所对应的作物也都要种在B里
    这就相当于选择一个点集,其中每个点的指向的点也在点集中,使这样一个点权和最大
    很容易想到是一个最大权闭合子图问题,最大权闭合子图的做法具体见bzoj1497,这里就不多说
    这种调整思路和判断混合图欧拉回路颇有异曲同工之妙

    这里采用的是第一种方法

      1 const inf=100000007;
      2 type node=record
      3        next,flow,point:longint;
      4      end;
      5 
      6 var edge:array[0..4000010] of node;
      7     p,numh,h,d,cur,pre:array[0..40010] of longint;
      8     t,x,y,k,i,j,n,m,len,a,s:longint;
      9 
     10 function min(a,b:longint):longint;
     11   begin
     12     if a>b then exit(b) else exit(a);
     13   end;
     14 
     15 procedure add(x,y,f:longint);
     16   begin
     17     inc(len);
     18     edge[len].point:=y;
     19     edge[len].flow:=f;
     20     edge[len].next:=p[x];
     21     p[x]:=len;
     22   end;
     23 
     24 function sap:longint;
     25   var i,j,q,tmp,u,neck:longint;
     26   begin
     27     sap:=0;
     28     fillchar(h,sizeof(h),0);
     29     numh[0]:=t+1;
     30     for i:=0 to t do
     31       cur[i]:=p[i];
     32     u:=0;
     33     sap:=0;
     34     neck:=inf;
     35     while h[0]<t+1 do
     36     begin
     37       d[u]:=neck;
     38       i:=cur[u];
     39       while i<>-1 do
     40       begin
     41         j:=edge[i].point;
     42         if (edge[i].flow>0) and (h[u]=h[j]+1) then
     43         begin
     44           pre[j]:=u;
     45           cur[u]:=i;
     46           neck:=min(neck,edge[i].flow);
     47           u:=j;
     48           if u=t then
     49           begin
     50             sap:=sap+neck;
     51             while u<>0 do
     52             begin
     53               u:=pre[u];
     54               j:=cur[u];
     55               dec(edge[j].flow,neck);
     56               inc(edge[j xor 1].flow,neck);
     57             end;
     58             neck:=inf;
     59           end;
     60           break;
     61         end;
     62         i:=edge[i].next;
     63       end;
     64       if i=-1 then
     65       begin
     66         dec(numh[h[u]]);
     67         if numh[h[u]]=0 then exit;
     68         q:=-1;
     69         tmp:=t;
     70         i:=p[u];
     71         while i<>-1 do
     72         begin
     73           j:=edge[i].point;
     74           if edge[i].flow>0 then
     75             if h[j]<tmp then
     76             begin
     77               q:=i;
     78               tmp:=h[j];
     79             end;
     80           i:=edge[i].next;
     81         end;
     82         h[u]:=tmp+1;
     83         cur[u]:=q;
     84         inc(numh[h[u]]);
     85         if u<>0 then
     86         begin
     87           u:=pre[u];
     88           neck:=d[u];
     89         end;
     90       end;
     91     end;
     92   end;
     93 
     94 begin
     95   len:=-1;
     96   fillchar(p,sizeof(p),255);
     97   readln(n);
     98   for i:=1 to n do
     99   begin
    100     read(x);
    101     s:=s+x;
    102     add(0,i,x);
    103     add(i,0,0);
    104   end;
    105   readln;
    106   for i:=1 to n do
    107   begin
    108     read(h[i]);
    109     s:=s+h[i];
    110   end;
    111   readln(m);
    112   t:=m*2+n+1;
    113   for i:=1 to n do
    114   begin
    115     add(i,t,h[i]);
    116     add(t,i,0);
    117   end;
    118   for i:=1 to m do
    119   begin
    120     read(k,x,y);
    121     s:=s+x+y;
    122     add(0,i+n,x);
    123     add(i+n,0,0);
    124     add(i+n+m,t,y);
    125     add(t,i+n+m,0);
    126     for j:=1 to k do
    127     begin
    128       read(a);
    129       add(i+n,a,inf);
    130       add(a,i+n,0);
    131       add(a,i+n+m,inf);
    132       add(i+n+m,a,0);
    133     end;
    134     readln;
    135   end;
    136   writeln(s-sap);
    137 end.
    View Code
  • 相关阅读:
    二维数组的最大联通子数组
    四则运算网页终结版
    Python+Selenium进阶版(四)-封装一个自己的类-浏览器引擎类
    Python+Selenium进阶版(三)- 二次封装Selenium中几个方法
    Python+Selenium进阶版(二)- Python中类/函数/模块的简单介绍
    Python+Selenium进阶版 (一)- Python IDE工具-PyCharm的安装和使用
    Python+Selenium学习-Xpat增强梳理版
    Python+Selenium练习(三十一)- 截图并保存
    Python+Selenium练习(三十)- 获取页面元素的href属性
    Python+Selenium练习(二十九)- 获取当前页面全部图片信息
  • 原文地址:https://www.cnblogs.com/phile/p/4473069.html
Copyright © 2011-2022 走看看