现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的,而且现在的兔子还比较笨,它们只有两个窝,现在你做为狼王,面对下面这样一个网格的地形:
左上角点为(1,1),右下角点为(N,M)(上图中N=4,M=5).有以下三种类型的道路 1:(x,y)<==>(x+1,y) 2:(x,y)<==>(x,y+1) 3:(x,y)<==>(x+1,y+1) 道路上的权值表示这条路上最多能够通过的兔子数,道路是无向的. 左上角和右下角为兔子的两个窝,开始时所有的兔子都聚集在左上角(1,1)的窝里,现在它们要跑到右下解(N,M)的窝中去,狼王开始伏击这些兔子.当然为了保险起见,如果一条道路上最多通过的兔子数为K,狼王需要安排同样数量的K只狼,才能完全封锁这条道路,你需要帮助狼王安排一个伏击方案,使得在将兔子一网打尽的前提下,参与的狼的数量要最小。因为狼还要去找喜羊羊麻烦.
【题解】
乍一看是最大流问题,然后就发现直接写应该会爆,于是上网找了一下发现可以构造对偶图(也就是先连首尾,然后一个小回路当一个点,两个点之间连一条权值是原来两个回路中间边的权值的边,最后删掉连接首尾的边)然后就是求解最短路问题了。
【代码】
program p1001;
type
edge = record
y, next, l: longint;
end;
var
a: array[-1..6000000] of edge;
b: array[0..1000, 0..1000, 0..1] of longint;
pd: array[0..2000000] of boolean;
d0, q, f: array[0..2000000] of int64;
i, j, m, n, x, n0, k: longint;
procedure insert(x, y, l: longint);
begin
Inc(a[-1].y);
a[a[-1].y].y := y;
a[a[-1].y].l := l;
a[a[-1].y].next := f[x];
f[x] := a[-1].y;
end;
procedure SPFA;
var
h, t, i, j, m: longint;
begin
for i := 0 to 2000000 do
d0[i] := maxlongint div 2;
q[0] := 0;
h := 0;
t := 0;
pd[0] := True;
d0[0] := 0;
while h <> t + 1 do
begin
m := q[h];
h := (h + 1) mod 5000000;
pd[m] := False;
i := f[m];
while i <> 0 do
begin
j := a[i].y;
if d0[m] + a[i].l < d0[j] then
begin
d0[j] := d0[m] + a[i].l;
if not pd[j] then
begin
if d0[j] < d0[q[h]] then
begin
h := (h + 4999999) mod 5000000;
q[h] := j;
end
else
begin
t := (t + 1) mod 5000000;
q[t] := j;
end;
pd[j] := True;
end;
end;
i := a[i].next;
end;
end;
end;
begin
readln(m, n);
for i := 1 to m - 1 do
for j := 1 to n - 1 do
begin
Inc(n0);
b[i, j, 0] := n0;
Inc(n0);
b[i, j, 1] := n0;
end;
k := n0 + 1;
for i := 1 to m do
for j := 1 to n - 1 do
begin
Read(x);
if i = 1 then
insert(b[i, j, 1], k, x)
else
if i = m then
insert(0, b[i - 1, j, 0], x)
else
begin
insert(b[i, j, 1], b[i - 1, j, 0], x);
insert(b[i - 1, j, 0], b[i, j, 1], x);
end;
end;
for i := 1 to m - 1 do
for j := 1 to n do
begin
Read(x);
if j = 1 then
insert(0, b[i, j, 0], x)
else
if j = n then
insert(b[i, j - 1, 1], k, x)
else
begin
insert(b[i, j, 0], b[i, j - 1, 1], x);
insert(b[i, j - 1, 1], b[i, j, 0], x);
end;
end;
for i := 1 to m - 1 do
for j := 1 to n - 1 do
begin
Read(x);
insert(b[i, j, 0], b[i, j, 1], x);
insert(b[i, j, 1], b[i, j, 0], x);
end;
spfa;
writeln(d0[k]);
end.