描述 Description
现在小朋友们最喜欢的 “喜羊羊与灰太狼”, 话说灰太狼抓羊不到,但抓兔子还是比较在行的,而且现在的兔子还比较笨,它们只有两个窝,现在你做为狼王,面对下面这样一个网格的地形:

左上角点为 (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 只狼,才能完全封锁这条道路,你需要帮助狼王安排一个伏击方案,使得在将兔子一网打尽的前提下,参与的狼的数量要最小。因为狼还要去找喜羊羊麻烦.
输入格式 InputFormat
第一行为 N,M. 表示网格的大小,N,M 均小于等于 1000. 接下来分三部分第一部分共 N 行,每行 M-1 个数,表示横向道路的权值. 第二部分共 N-1 行,每行 M 个数,表示纵向道路的权值. 第三部分共 N-1 行,每行 M-1 个数,表示斜向道路的权值. 输入文件保证不超过 10M.
输出格式 OutputFormat
输出一个整数,表示参与伏击的狼的最小数量.
样例输入 SampleInput
3 4
5 6 4
4 3 1
7 5 3
5 6 7 8
8 7 6 5
5 5 5
6 6 6
样例输出 SampleOutput
14
代码 Code
试了一下平面图最小割转对偶图最短路的写法。所以以后还是必须得开循环队列么。
转对偶图的时候可以参考下面这张:

#include <stdio.h>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
#define inf 0x7fffffff/27.11
struct side
{
int to,next,v;
};
side a[6000005];
int head[2000005];
int dis[2000005],f[6000005];
bool used[2000005];
int i,j,t,n,m,l,r,k,s,z,y,x,sn;
void add(int x,int y,int z)
{
a[++sn].to=y;a[sn].v=z;a[sn].next=head[x];head[x]=sn;
a[++sn].to=x;a[sn].v=z;a[sn].next=head[y];head[y]=sn;
}
void build()
{
int i,j,t;
//====================
for (i=1;i<=m-1;i++)
{
scanf("%d",&t);
add(2*i,z,t);
}
for (i=2;i<=n-1;i++)
{
for (j=1;j<=m-1;j++)
{
scanf("%d",&t);
add((i-2)*2*(m-1)+2*j-1,(i-1)*2*(m-1)+2*j,t);
}
}
for (i=1;i<=m-1;i++)
{
scanf("%d",&t);
add(s,(n-2)*2*(m-1)+2*i-1,t);
}
//====================
for (i=1;i<=n-1;i++)
{
scanf("%d",&t);
add(s,(i-1)*2*(m-1)+1,t);
for (j=2;j<=m-1;j++)
{
scanf("%d",&t);
add((i-1)*2*(m-1)+2*j-2,(i-1)*2*(m-1)+2*j-1,t);
}
scanf("%d",&t);
add((i-1)*2*(m-1)+2*(m-1),z,t);
}
//=====================
for (i=1;i<=n-1;i++)
{
for (j=1;j<=m-1;j++)
{
scanf("%d",&t);
add((i-1)*2*(m-1)+2*j-1,(i-1)*2*(m-1)+2*j,t);
}
}
}
void spfa()
{
int i,j,t,k;
l=0;r=l+1;f[l]=s;
for (i=1;i<=z;i++) dis[i]=inf;
memset(used,false,sizeof(used));
used[s]=true;
while (r!=l)
{
if (l>6000000) l-=6000000;
t=f[l];l++;k=head[t];
while (k!=0)
{
if (dis[a[k].to]>dis[t]+a[k].v)
{
dis[a[k].to]=dis[t]+a[k].v;
if (used[a[k].to]==false)
{
used[a[k].to]=true;
f[r++]=a[k].to;
if (r==6000000) r-=6000000;
}
}
k=a[k].next;
}
used[t]=false;
}
}
int main()
{
scanf("%d%d",&n,&m);
if (n==1 && m==1)
{
printf("0\n");
return 0;
}
if (n==1)
{
t=0x7fffffff;
for (i=1;i<=m-1;i++)
{
scanf("%d",&s);
t=min(t,s);
}
printf("%d\n",t);
return 0;
}
z=2*(n-1)*(m-1)+1;
s=0;
sn=0;
memset(a,0,sizeof(a));
memset(head,0,sizeof(head));
build();
spfa();
printf("%d\n",dis[z]);
return 0;
}