ZKW费用流的理解

ORZ ZKW费用流这样的神牛算法,也只有对最短路理解很深度人才能想得出来了吧

下面是我对这个算法的理解

ZKW算法主要分为AUG和Modlabel两个过程

其中Aug过程与普通的最大流DFS增广求法相似,但加入一个限制条件

满足等式Dist[U]=Dist[V]+edge.cost才允许增广

代码如下

int aug(int u,int flow)
  {   if (u==T) {ans+=flow*dis[S]; return flow;}
      vis[u]=1; int now=0;
      for (int i=base[u];i;i=v[i].next)
      { int x=v[i].x; 
        if (vis[x]||!v[i].f||dis[u]!=dis[x]+v[i].cost)
          continue;
       int tmp=aug(x,min(flow-now,v[i].f));
       if (tmp) v[i].f-=tmp; v[v[i].op].f+=tmp;
       now+=tmp;  if (now==flow) return flow; 
     } return now;
  }
Aug

你可能感到奇怪,这个过程并不会进行,应为一开始Dist应该都为0,所以还需要Modlabel来修改距离

int modlable()
  {  int del=inf;
     for (int i=S;i<=T;i++)
     if (vis[i]) 
     for (int j=base[i];j;j=v[j].next)
     if (v[j].f) {int x=v[j].x;  
      if (!vis[x]) del=min(del,dis[x]+v[j].cost-dis[i]);}
     if (del==inf) return 0;
     for (int i=S;i<=T;i++)
       if (vis[i]) vis[i]=0,dis[i]+=del,cur[i]=base[i]; return 1;
   }
Modlabel

当流网络不能再增广的时候,我们就修改距离,我们找出所有还有流量的边,并且边的起点被访问,但边终点未被访问

显然这些边都是因为不满足Dist[U]=Dist[V]+edge.cost才被阻断的,我们记录所有满足边下中Dist[V]+edge.cost-Dist[U]最小值

这样就能优先找出最短增广路,就能求出费用流了

最后将两个过程和在一起

int zkw()
  {  for (int i=S;i<=T;i++) cur[i]=base[i];
     do {while (aug(S,inf)) memset(vis,0,sizeof(vis));}
     while (modlable()); printf("%d\n",ans);
   }
ZKW

 

转载于:https://www.cnblogs.com/williamchenwl/p/3691917.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值