「ICPC-Beijing 2006」狼抓兔子

又是一个网络流。

传送门

洛谷P4001

BZOJ1001

题解

最大流最小割定理的一个简单运用。

很显然题目中要求的就是图中网络的最小割。

所以直接求最大流就好了。

注意题目中的边是双向的。

数据稍微有点大,但是毕竟Dinic可是n方过百万的,直接搞就好了,注意要稍微加一些优化。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=1000005,maxe=6000005,inf=0x3F3F3F3F;
int n,m,S,T,tot,lnk[maxn],son[maxe],nxt[maxe],cap[maxe],que[maxn],dep[maxn],ans;
inline char nc()
{
const int S=131072;static char buf[S],*L,*R;
return L==R&&(R=(L=buf)+fread(buf,1,S,stdin),L==R)?EOF:*L++;
}
inline int read()
{
int ret=0,f=1;char ch=nc();
while(ch<'0'||ch>'9'){if(ch=='-')f=-f;ch=nc();}
while(ch>='0'&&ch<='9'){ret=ret*10+ch-'0';ch=nc();}
return ret*f;
}
inline void add_e(int x,int y,int z){tot++;son[tot]=y;cap[tot]=z;nxt[tot]=lnk[x];lnk[x]=tot;}
int DFS(int now,int lim)
{
if(lim==0||now==T) return lim;
int ret=0;
for(int i=lnk[now];i&&lim;i=nxt[i])
{
if(cap[i]>0&&dep[now]+1==dep[son[i]])
{
int tep=DFS(son[i],min(lim,cap[i]));
if(tep)
{
ret+=tep;
lim-=tep;
cap[i]-=tep;
cap[(i&1)?i+1:i-1]+=tep;
}
else dep[son[i]]=-1;
}
}
return ret;
}
inline void Dinic()
{
while(true)
{
int hed=0,til=1;
memset(dep,63,sizeof(dep));
que[1]=S;dep[S]=1;
while(hed!=til)
{
hed++;
for(int i=lnk[que[hed]];i;i=nxt[i])
{
if(cap[i]>0&&dep[que[hed]]+1<dep[son[i]])
{
dep[son[i]]=dep[que[hed]]+1;
til++;
que[til]=son[i];
}
}
}
if(dep[T]==inf) return;
ans+=DFS(S,inf);
}
}
int main()
{
n=read();m=read();S=1;T=n*m;
for(int i=1;i<=n;i++)
{
for(int j=1;j<m;j++)
{
int a=(i-1)*m+j,b=(i-1)*m+j+1,c=read();
add_e(a,b,c);add_e(b,a,c);
}
}
for(int i=1;i<n;i++)
{
for(int j=1;j<=m;j++)
{
int a=(i-1)*m+j,b=i*m+j,c=read();
add_e(a,b,c);add_e(b,a,c);
}
}
for(int i=1;i<n;i++)
{
for(int j=1;j<m;j++)
{
int a=(i-1)*m+j,b=i*m+j+1,c=read();
add_e(a,b,c);add_e(b,a,c);
}
}
Dinic();
printf("%d\n",ans);
return 0;
}