最大流Dinic

本文详细介绍了Dinic最大流算法的基本原理与实现步骤。包括如何通过搭建边集结构存储图,利用BFS搜索增广路径,以及通过DFS进行流量增广等关键环节。特别解释了反向边的作用及意义。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Dinic是一种利用增广路径解决最大流的算法,主要利用BFS寻找增光路径直到无法增广
首先是搭边

struct ed
{
    int to,cap,next;    //cap表示该边剩余容量
}e[maxm];
int level[maxn],head[maxn];

void add(int from,int to,int cap)  //利用堆储存
{
    e[cnt].to=to;
    e[cnt].cap=cap;
    e[cnt].next=head[from];
    head[from]=cnt++;
    swap(from,to);    //建立反向边
    e[cnt].to=to;
    e[cnt].cap=0;
    e[cnt].next=head[from];
    head[from]=cnt++;
}

反向边有什么用?
反向边是搭边过程中重要的一环,一般来说反向边的from与to跟原边相反,剩余容量为0,这样在增广过程中若发现更优解我们就可以使流量从反向边回流。

接下来利用BFS寻找增广路

bool bfs()
{
    memset(level,-1,sizeof(level));
    level[Start]=0;  //level记录层数为DFS做准备
    queue<int>q;
    q.push(Start);
    while(!q.empty())
    {
        int i,u=q.front();
        q.pop();
        for(i=head[u];i!=-1;i=e[i].next)
        {
            int v=e[i].to;
            if(e[i].cap>0&&level[v]==-1)  //若该边还有剩余容量并且没有被遍历
            {
                level[v]=level[u]+1;
                q.push(v);
            }
        }
    }
    return level[End]!=-1;     //是否找到增广路
}

找到增广路就对其进行增广

int dfs(int u,int f)  //当前点与当前流量
{
    if(u==End||!f) return f;
    int k,i;
    for(i=head[u];i!=-1;i=e[i].next)
    {
        int v=e[i].to;
        if(e[i].cap>0&&level[u]+1==level[v])  //沿level进行增广
        {
            k=dfs(v,min(f,e[i].cap));
            if(k>0)
            {
                e[i].cap-=k;     //当前边边减去流量k
                e[i^1].cap+=k;   //当前反向边加上流量k
                return k;
            }
        }
    }
    level[u]=-1;
    return 0;
}

Dinic

int dinic()
{
    int s=0,f;
    while(bfs())  //若找到增广路
    {
        while((f=dfs(Start,0x3f3f3f3f))>0) s+=f;  //增广并返回增广的流量
    }
    return s;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值