bzoj1001 狼抓兔子

题目

bzoj1001

题解

网络流很经典的建模,先建对偶图,再用最短路跑最小割,注意以左下为s,右上为t

代码

include

include

include

include

include

include

include

define N 6001000

define M 2000010

using namespace std;

int n,m,s,t;

int read()
{
int cnt=0;char ch=getchar();
while (!isdigit(ch)) ch=getchar();
while (isdigit(ch)) cnt=cnt*10+ch-'0',ch=getchar();
return cnt;
}

int num,a[N],b[N],w[N],nt[N],p[M];
void add(int x,int y,int v)
{
a[++num]=x;b[num]=y;w[num]=v;
nt[num]=p[x];p[x]=num;
a[++num]=y;b[num]=x;w[num]=v;
nt[num]=p[y];p[y]=num;
}

int up(int x,int y) {return (x-1)(m-1)2+y;}
int down(int x,int y) {return (x-1)(m-1)2+(m-1)+y;}

void build()
{
s=0;t=(m-1)(n-1)2+1;
for(int i=1;i<=n;i++)
for(int j=1;j<m;j++)
{
int v=read();
if(i1) add(up(i,j),t,v);
else if(i
n) add(s,down(i-1,j),v);
else add(down(i-1,j),up(i,j),v);
}
for(int i=1;i<n;i++)
for(int j=1;j<=m;j++)
{
int v=read();
if(j1) add(s,down(i,j),v);
else if(j
m) add(up(i,j-1),t,v);
else add(up(i,j-1),down(i,j),v);
}
for(int i=1;i<n;i++)
for(int j=1;j<m;j++)
{
int v=read();
add(up(i,j),down(i,j),v);
}
}

int dis[M];bool flag[M];queue q;
void spfa()
{
memset(dis,127,sizeof(dis));
q.push(s);flag[s]=1;dis[s]=0;
while(!q.empty())
{
int k=q.front();q.pop();
for(int e=p[k];e;e=nt[e])
{
int kk=b[e];
if(dis[kk]-dis[k]>w[e])
{
dis[kk]=dis[k]+w[e];
if(!flag[kk]) {flag[kk]=1;q.push(kk);}
}
}
flag[k]=0;
}
}

int main()
{
n=read();m=read();
build();
spfa();
printf("%d",dis[t]);
return 0;
}

posted @ 2017-08-18 11:05  XYZinc  阅读(176)  评论(0)    收藏  举报