割
割是一种对网络流点的划分方式
对于一个网络流图G(V,E),划分为S和T两部分,其中T=V-S,源点s∈S,汇点t∈T
净流f(S,T)表示穿过割(S,T)的流量之和
f(S,T)=Σf(u,v) | u∈S,v∈T
割的容量C(S,T)为所有从S到T的边容量之和
C(S,T)=Σc(u,v) | u∈S,v∈T
f(S,T)算穿过割(S,T)的正反向边,而C(S,T)只算正向边
最小割指容量最小的可能的割
最大流最小割定理
对于一个网络流图G(V,E),最大流的值等于最小割的容量
增广路
在学习最大流时,可以使用增广路算法来求最大流,但是增广路算法都是在找不到增广路时,就得出了最大流的值。
证明
若残留网络Gf不存在增广路,则Gf中不存在路径从s到达t
定义S集合为:残留网络中s可到达的点
(S,T)构成一个割(S,T)
若f(u,v)小于c(u,v),则Gf(u,v)>0,与上述“不存在路径从s到达t”矛盾
所以f(S,T)=C(S,T)
因为f(S,T)<最小割,又因为f(S,T)=C(S,T)
所以f(S,T)为最大流
求最小割
据“最大流最小割定理”,可使用求最大流的算法求最小割
这里使用dinic算法求最小割
部分代码
void bfs()
{
memset(h,-1,sizeof(h));
q[1]=1;
h[1]=0;
int qh=1,qt=1;
while (qh<=qt)
{
for (int i=linkk[q[qh]];i;i=e[i].next)
if (h[e[i].y]==-1 && e[i].v)
{
h[e[i].y]=h[q[qh]]+1;
q[++qt]=e[i].y;
}
qh++;
}
if (h[n]!=-1) flag=true;
}
int dfs(int k,int delta)
{
if (k==n) return delta;
int ma=0;
for (int i=linkk[k];i && ma<delta;i=e[i].next)
if (h[e[i].y]==h[k]+1 && e[i].v)
{
if (add=dfs(e[i].y,min(e[i].v,delta-ma)))
{
ma+=add;
e[i].v-=add;
e[i^1].v+=add;
}
}
if (!ma) h[k]=-1;
return ma;
}