您的位置:首页 > 其它

BZOJ 1001 [BeiJing2006]狼抓兔子

2017-01-25 21:19 246 查看
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1001

题意: ...

很容易想到求的是一个最小割=最大流。

之前一直用的刘汝佳的模板STL过题,很久没用过数组模拟了。

再次熟悉一下写法,first数组是索引数组,标记的结点的最后一条边,利用next数组找到上一条边。

#include <bits/stdc++.h>

using namespace std;

#define N 1100000
int n,m,first
,next[N*6],v[N*6],w[N*6],tot,jy,ans,vis
,S,T,xx,pos
;

void Add(int x,int y,int z)
{
w[tot] = z;
v[tot] = y;
next[tot] = first[x];
first[x] = tot++;
}

void add(int x,int y,int z)
{
Add(x,y,z);
Add(y,x,z);
}

bool bfs()
{
memset(vis,-1,sizeof(vis)),vis[S]=0;
queue<int>q;
q.push(S);
while(!q.empty())
{
int t=q.front();
q.pop();
for(int i=first[t]; ~i; i=next[i])
if(w[i]&&vis[v[i]]==-1)
vis[v[i]]=vis[t]+1,q.push(v[i]);
}
return vis[T]!=-1;
}

int dfs(int x,int y)
{
if(x==T)return y;
int r=0;
for(int i=first[x]; ~i&&y>r; i=next[i])
if(w[i]&&vis[v[i]]==vis[x]+1)
{
int t=dfs(v[i],min(y-r,w[i]));
w[i]-=t,w[i^1]+=t,r+=t;
}
if(!r)vis[x]=-1;
return r;
}

int main()
{
memset(first,-1,sizeof(first));
scanf("%d%d",&n,&m);
S=m+1,T=n*m+m;
for(int i=1; i<=n; i++)
for(int j=1; j<m; j++)
scanf("%d",&xx),add(i*m+j,i*m+j+1,xx);
for(int i=1; i<n; i++)
for(int j=1; j<=m; j++)
scanf("%d",&xx),add(i*m+j,(i+1)*m+j,xx);
for(int i=1; i<n; i++)
for(int j=1; j<m; j++)
scanf("%d",&xx),add(i*m+j,(i+1)*m+j+1,xx);

while(bfs())
while(jy=dfs(S,0x3fffffff))
ans+=jy;
printf("%d\n",ans);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: