【省选专题一】图论 jzoj 3821. 【NOI2015模拟9.9】文理分科 最小割

Description

这里写图片描述

Input

这里写图片描述

Output

这里写图片描述

Sample Input

3 4
13 2 4 13
7 13 8 12
18 17 0 5
8 13 15 4
11 3 8 11
11 18 6 5
1 2 3 4
4 2 3 2
3 1 0 4
3 2 3 2
0 2 2 1
0 2 4 4

Sample Output

152

Data Constraint

这里写图片描述

Hint

这里写图片描述

分析:因为每个点会分在两个不同的集合中的一个(文科or理科),考虑最小割。
考虑对自己的影响,我们发现,把每个点拆成4个点。
从S连一条art[x]边到点x1,x1连一条INF的边到x2,x2连一条science[x]的边到T。显然不可能割掉第二条边(INF),那么割掉第一条边表示选理科,割第三条边表示选文科(画图可知)。
从S连一条same_art[x]到x3,x3连一些边到到周围的4个点的x1包括自己连一条INF的边。显然不可能割掉x3到x1,x1到x2的边(INF),那么割掉S到x3表示周围不一定选文科,割掉x2到T的全部5条边表示全选文科。理科同理,把x3变为x4。具体连边可以看代码,正确性可以通过画图得到。

代码:

const
 maxv=500000;
 maxn=105*105*4;
 inf=maxlongint div 4;
type
 node=record
  y,c,op,next:longint;
 end;

var
 g:array [1..maxv] of node;
 ls,dis,cur:Array [0..maxn] of longint;
 list:array [0..maxn] of longint;
 n,m,e,s,t,ans,tot,c,d:longint;

procedure add(u,v,c:longint);
 begin
  inc(e);
  g[e].y:=v; g[e].c:=c; g[e].op:=e+1; g[e].next:=ls[u]; ls[u]:=e;
  inc(e);
  g[e].y:=u; g[e].c:=0; g[e].op:=e-1; g[e].next:=ls[v]; ls[v]:=e;
 end;

function bfs:boolean;
 var
  i,head,tail,u:longint;
begin
 for i:=s to t do
  dis[i]:=0;
 dis[s]:=1;
 head:=0; tail:=1;
 list[tail]:=s;
 repeat
  head:=(head+1) mod maxv;
  u:=list[head];
  i:=ls[u];
  while i>0 do
   begin
    if (g[i].c<>0) and (dis[g[i].y]=0) then
     begin
      dis[g[i].y]:=dis[u]+1;
      if g[i].y=t then exit(true);
      tail:=(tail+1) mod maxv;
      list[tail]:=g[i].y;
     end;
    i:=g[i].next;
   end;
 until head=tail;
 exit(false);
end;

function min(x,y:longint):longint;
 begin
  if x<y then exit(x)
         else exit(y);
 end;

function dfs(x,maxf:longint):longint;
 var ret,i,f:longint;
begin
 if (x=t) or (maxf=0) then exit(maxf);
 ret:=0;
 i:=cur[x];
 while i>0 do
  begin
   if (g[i].c<>0) and (dis[g[i].y]=dis[x]+1) then
    begin
     f:=dfs(g[i].y,min(maxf-ret,g[i].c));
     dec(g[i].c,f);
     inc(g[g[i].op].c,f);
     ret:=ret+f;
    end;
   if ret=maxf then break;
   i:=g[i].next;
  end;
 exit(ret);
end;


procedure dinic;
 var i:longint;
begin
 while bfs do
  begin
   for i:=s to t do cur[i]:=ls[i];
    ans:=ans-dfs(s,inf);
  end;
end;

function po(x,y,z:longint):longint;
 begin
  exit((m*(x-1)+y-1)*4+z);
 end;

procedure init;
 var i,j,w,x,y:longint;
begin
 readln(n,m);
 s:=0; t:=4*n*m+4;
 for i:=1 to n do
  for j:=1 to m do
   begin
    read(x);
    add(s,po(i,j,1),x);
    add(po(i,j,1),po(i,j,2),inf);
    ans:=ans+x;
   end;
 for i:=1 to n do
  for j:=1 to m do
   begin
    read(x);
    add(po(i,j,2),t,x);
    ans:=ans+x;
   end;
 for i:=1 to n do
  for j:=1 to m do
   begin
    read(x);
    ans:=ans+x;
    add(s,po(i,j,4),x);
    if i>1 then
     add(po(i,j,4),po(i-1,j,1),inf);
    if j>1 then
     add(po(i,j,4),po(i,j-1,1),inf);
    if i<n then
     add(po(i,j,4),po(i+1,j,1),inf);
    if j<m then
     add(po(i,j,4),po(i,j+1,1),inf);
    add(po(i,j,4),po(i,j,1),inf);
   end;
 for i:=1 to n do
  for j:=1 to m do
   begin
    read(x);
    ans:=ans+x;
    add(po(i,j,3),t,x);
    if i>1 then
     add(po(i-1,j,2),po(i,j,3),inf);
    if j>1 then
     add(po(i,j-1,2),po(i,j,3),inf);
    if i<n then
     add(po(i+1,j,2),po(i,j,3),inf);
    if j<m then
     add(po(i,j+1,2),po(i,j,3),inf);
    add(po(i,j,2),po(i,j,3),inf);
   end;
end;

begin
 init;
 dinic;
 writeln(ans);
end.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值