Dinic前向星

本文深入探讨了Dinic算法的原理与应用,这是一种高效的网络流算法,用于解决最大流问题。文章详细介绍了算法的BFS和DFS部分,并通过代码示例展示了如何在C++中实现Dinic算法。
#include <queue>
#include <algorithm>
#include <iostream>
#include <stdio.h>
#include <string.h>

using namespace std;
#define ll long long
#define mem(a, b) memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
#define DBG printf("this is a input\n")

ll gcd(ll a, ll b) {
    return b == 0 ? a : gcd(b, a % b);
}

ll lcm(ll a, ll b) {
    return a / gcd(a, b) * b;
}
queue<int>q;
int n, m, cnt, ans, st ,ed;
int head[205],level[205];
struct e
{
    int to;
    int next;
    int c;
}edge[205*2];
void add(int f ,int t, int w)
{
    edge[cnt].to = t;
    edge[cnt].c = w;
    edge[cnt].next = head[f];
    head[f] = cnt ++;
}
bool DinicBfs(int s, int e)
{
    mem(level,0);
    while(!q.empty())
        q.pop();
    q.push(s);
    level[s] = 1;
    while(!q.empty())
    {
        int root = q.front();
        q.pop();
        for(int i = head[root] ; i != 0 ; i = edge[i].next)
        {
            int v = edge[i].to;
            if(!level[v] && edge[i].c > 0)
            {
                level[v] = level[root] + 1;
                q.push(v);
            }
        }
    }
    return level[e] != 0;
}
int DinicDfs(int root, int flow)
{
    if(root == ed)
        return flow;
    int newflow;
    for(int i = head[root] ; i != 0 ; i = edge[i].next)
    {
        if(edge[i].c > 0 && level[edge[i].to] == level[root] + 1 && (newflow = DinicDfs(edge[i].to,min(edge[i].c,flow))))
        {
            edge[i].c -= newflow;
            edge[i^1].c += newflow;
            return newflow;
        }
    }
    return 0;
}
void Dinic()
{
    ans = 0;
    while(DinicBfs(st,ed))
    {
        while(int add = DinicDfs(1,INF)) {
            ans += add;
        }
    }
}
int main(void)
{
    while(scanf("%d %d",&m , &n)!=EOF)
    {
        mem(head,0);
        cnt = 1;
        for(int i = 1 ; i <= m ; i ++)
        {
            int f ,t ,w;
            scanf("%d %d %d",&f ,&t, &w);
            add(f,t,w);
            add(t,f,0);
        }
        st = 1;
        ed = n;
        Dinic();
        printf("%d\n",ans);
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值