网络流-最大流

最大流

dinic

  • 思路:先bfs找出每个点的深度,然后按照深度进行dfs
bool bfs()
{
    memset(dis,-1,sizeof(dis));
    memset(vst,0,sizeof(vst));
    queue <int> q;
    q.push(S);dis[S]=0;vst[S]=1;
    while(!q.empty())
    {
        int a=q.front(),x;q.pop();
        if(a==T)return 1;
        for(int i=h[a];i;i=g[i].next)
        {
            x=g[i].to;
            if(g[i].v>0&&vst[x]==0)
            {
                vst[x]=1;dis[x]=dis[a]+1;q.push(x);
            }
        }
    }
    return 0;
}
long long dfs(int a,long long maxx)
{
    long long res=0,dlt;
    int x;
    if(a==T||maxx==0)return maxx;
    for(int i=h[a];i;i=g[i].next)
    {
        x=g[i].to;
        if(g[i].v<=0||dis[x]!=dis[a]+1)continue;
        dlt=dfs(x,min(maxx,g[i].v));
        if(dlt==0)dis[x]=0;
        g[i].v-=dlt;g[i^1].v+=dlt;
        res+=dlt;maxx-=dlt;
        if(maxx==0)return res;
    }
    return res;
}
long long dinic()
{
    long long ans=0;
    while(bfs())
    {
        ans+=dfs(S,inf);
    }
    return ans;
}

sap

  • 思路:利用$ d[ ] $数组记录每个点的当前深度,从深度高的点到深度小1的点dfs,
    $ gap[ ] $ 记录每个深度的点的数量,当增加当前点的深度后原深度的点的数量为0时,出现断层,无法继续dfs,标记$ d[T]=ed $然后退出循环
long long dfs(int a,long long maxx)
{
    if(a==T||maxx==0)return maxx;
    int x,i;
    long long dlt,res=0;
    for(i=h[a];i;i=g[i].next)
    {
        x=g[i].to;
        if(d[x]!=d[a]-1||g[i].v<=0)continue;
        dlt=dfs(x,min(maxx,g[i].v));
        g[i].v-=dlt;g[i^1].v+=dlt;
        res+=dlt;maxx-=dlt;
        if(maxx==0||d[T]==ed)return res;
    }
    if(--gap[d[a]]==0)d[T]=ed;
    d[a]++;gap[d[a]]++;
    return res;
}
long long sap()
{
    long long ans=0;gap[0]=n;
    while(d[T]!=ed)
    {
        ans+=dfs(S,inf);
    }
    return ans;
}

转载于:https://www.cnblogs.com/jungezi/p/10457195.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值