您的位置:首页 > 其它

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

2018-01-11 15:57 453 查看
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.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: