bzoj3774

这算是最小割中比较难的吧

看到选取显然最小割

看到上下左右四个点我感觉肯定和染色相关

注意每个点的收益获得条件是[或],因此我们考虑拆点i‘, i

连边s-->i 流量为选择该点的代价, i-->i‘ 流量为该点的收益 i‘到撒谎上下左右,流量为正无穷,表示另一个条件

这样,要获得收益便一定要割断一边,就满足了或的性质

注意,另一种颜色的连边与这种颜色相反,由于染色可以得到二分图

所以另一种颜色的连边反过来建即可

  1 const inf=1000000007;
  2       dx:array[1..4] of longint=(0,0,-1,1);
  3       dy:array[1..4] of longint=(1,-1,0,0);
  4
  5 type node=record
  6        po,next,flow:longint;
  7      end;
  8
  9 var e:array[0..2000010] of node;
 10     numh,h,cur,p,pre,d:array[0..5010] of longint;
 11     a:array[0..51,0..51] of longint;
 12     ans,i,j,x,y,len,t,n,m,k:longint;
 13
 14 function min(a,b:longint):longint;
 15   begin
 16     if a>b then exit(b) else exit(a);
 17   end;
 18
 19 procedure add(x,y,f:longint);
 20   begin
 21     inc(len);
 22     e[len].po:=y;
 23     e[len].flow:=f;
 24     e[len].next:=p[x];
 25     p[x]:=len;
 26   end;
 27
 28 procedure build(x,y,f:longint);
 29   begin
 30     add(x,y,f);
 31     add(y,x,0);
 32   end;
 33
 34 function sap:longint;
 35   var i,j,u,neck,tmp,q:longint;
 36   begin
 37     for i:=0 to t do
 38       cur[i]:=p[i];
 39     sap:=0;
 40     u:=0;
 41     neck:=inf;
 42     numh[0]:=t+1;
 43     while h[0]<t+1 do
 44     begin
 45       i:=cur[u];
 46       d[u]:=neck;
 47       while i<>-1 do
 48       begin
 49         j:=e[i].po;
 50         if (e[i].flow>0) and (h[u]=h[j]+1) then
 51         begin
 52           neck:=min(neck,e[i].flow);
 53           pre[j]:=u;
 54           cur[u]:=i;
 55           u:=j;
 56           if u=t then
 57           begin
 58             sap:=sap+neck;
 59             while u<>0 do
 60             begin
 61               u:=pre[u];
 62               j:=cur[u];
 63               dec(e[j].flow,neck);
 64               inc(e[j xor 1].flow,neck);
 65             end;
 66             neck:=inf;
 67           end;
 68           break;
 69         end;
 70         i:=e[i].next;
 71       end;
 72       if i=-1 then
 73       begin
 74         dec(numh[h[u]]);
 75         if numh[h[u]]=0 then exit;
 76         tmp:=t;
 77         q:=-1;
 78         i:=p[u];
 79         while i<>-1 do
 80         begin
 81           j:=e[i].po;
 82           if e[i].flow>0 then
 83             if h[j]<tmp then
 84             begin
 85               tmp:=h[j];
 86               q:=i;
 87             end;
 88           i:=e[i].next;
 89         end;
 90         cur[u]:=q;
 91         h[u]:=tmp+1;
 92         inc(numh[h[u]]);
 93         if u<>0 then
 94         begin
 95           u:=pre[u];
 96           neck:=d[u];
 97         end;
 98       end;
 99     end;
100   end;
101
102 begin
103   len:=-1;
104   fillchar(p,sizeof(p),255);
105   readln(n,m);
106   t:=2*n*m+1;
107   for i:=1 to n do
108     for j:=1 to m do
109     begin
110       read(x);
111       inc(k); a[i,j]:=k;
112       if (i+j) mod 2=1 then build(0,a[i,j],x)
113       else build(a[i,j],t,x);
114     end;
115
116   for i:=1 to n do
117     for j:=1 to m do
118     begin
119       read(x);
120       ans:=ans+x;
121       if (i+j) mod 2=1 then build(a[i,j],a[i,j]+n*m,x)
122       else build(a[i,j]+n*m,a[i,j],x);
123     end;
124
125   for i:=1 to n do
126     for j:=1 to m do
127     begin
128       if (i+j) mod 2=1 then
129       begin
130         for k:=1 to 4 do
131         begin
132           x:=i+dx[k];
133           y:=j+dy[k];
134           if (x<=0) or (x>n) or (y<=0) or (y>m) then continue;
135           build(a[i,j]+n*m,a[x,y],inf);
136         end;
137       end
138       else begin
139         for k:=1 to 4 do
140         begin
141           x:=i+dx[k];
142           y:=j+dy[k];
143           if (x<=0) or (x>n) or (y<=0) or (y>m) then continue;
144           build(a[x,y],a[i,j]+n*m,inf);
145         end;
146       end;
147     end;
148
149   writeln(ans-sap);
150 end.

时间: 2024-08-05 00:56:27

bzoj3774的相关文章

【BZOJ3774】最优选择 最小割

[BZOJ3774]最优选择 Description 小N手上有一个N*M的方格图,控制某一个点要付出Aij的代价,然后某个点如果被控制了,或者他周围的所有点(上下左右)都被控制了,那么他就算是被选择了的.一个点如果被选择了,那么可以得到Bij的回报,现在请你帮小N选一个最优的方案,使得回报-代价尽可能大. Input 第一行两个正整数N,M表示方格图的长与宽. 接下来N行每行M个整数Aij表示控制的代价. 接下来N行每行M个整数Bij表示选择的回报. Output 一个整数,表示最大的回报-代

【bzoj3774】最优选择 网络流最小割

题目描述 小N手上有一个N*M的方格图,控制某一个点要付出Aij的代价,然后某个点如果被控制了,或者他周围的所有点(上下左右)都被控制了,那么他就算是被选择了的.一个点如果被选择了,那么可以得到Bij的回报,现在请你帮小N选一个最优的方案,使得回报-代价尽可能大. 输入 第一行两个正整数N,M表示方格图的长与宽. 接下来N行每行M个整数Aij表示控制的代价. 接下来N行每行M个整数Bij表示选择的回报. 输出 一个整数,表示最大的回报-代价(如果一个都不控制那么就是0). 样例输入 3 31 1

bzoj3774 最优选择

题目描述: 小N手上有一个N*M的方格图,控制某一个点要付出Aij的代价,然后某个点如果被控制了,或者他周围的所有点(上下左右)都被控制了,那么他就算是被选择了的.一个点如果被选择了,那么可以得到Bij的回报,现在请你帮小N选一个最优的方案,使得回报-代价尽可能大. 题解: 最开始以为是最大权闭合子图裸题,后来发现少了点什么-- 一般的图是正权->负权,但是这道题是负权->正权. 于是考虑拆点+最小割. 先假设手里拿着有所有的价值,即$\sum(b)$ 对于一个点有三种情况: 1.占领这个点,

TopCoder SRM 刷水

怎么样快速提高姿势水平呢?自信说应该做TopCoder! 于是我就看到了很多XJOI题,BZOJ题……好像可以搬些题呢! 简单整理一下,方便未来搬题(雾 462C:先考虑从某个点出发,其出边有不能走的边,到终点距离在最坏情况下的最小值.再考虑从某个点出发,还不知道不能走的边在哪时,到终点距离在最坏情况下的最小值.前者枚举每条出边跑最短路,后者反着跑最短路,然后和前者的答案取较大值. 463C:BZOJ2454,一个点最多只有三种转移,某些情况下只有两种,如果以这些点为根来看,整个转移的结构就是一

Day5网络流

算法 无源汇上下界可行流 先强制流过l的流量 从s到每个正权点连流量为l的流量 从每个负权点向t连-l的流量 如果容量为0,则不连边 有源汇上下界最大流 去掉下界 先求出可行流 再求S到T的最大流 有源汇上下界最小流 直接应用 poj1149 我的思路 建一个点S,到每个顾客,连INF的边,每个顾客 正解 1.用分层图,建n*m个点 2.直接从S向每个人连边,记录下每个猪圈打开的人的先后顺寻,先来的人向后来的人连边 BZOJ2406 Solution 路径覆盖模型 路径覆盖无交集 链覆盖可以有交