网络流-最小割

割是一种对网络流点的划分方式
对于一个网络流图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;
}

猜你喜欢

转载自blog.csdn.net/fsl123fsl/article/details/80463675