avatar
fireworks99
keep hungry keep foolish

最大流Dinic算法

Dinic

前面的网络流算法,每进行一次增广,都要做 一遍BFS,十分浪费。能否少做几次BFS? 这就是Dinic算法要解决的问题

Dinic是EK(SAP)的改进,但可能逊于ISAP

参考博客:https://blog.csdn.net/A_Comme_Amour/article/details/79356220

Code(模板) O(n n m)

#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

const int N = 10005;
const int INF = 0x3f3f3f3f;
typedef long long ll;

ll n, m;
int maxflow, deep[N];///deep深度

struct Edge
{
    int to, w, pre;
} a[N];

queue<int> q;
int cnt = -1, head[N], cur[N];///cur用于复制head

///cnt in this way can save the time
///我也试过cnt初始化为0,最后加个++cnt,但TLE
void add(int from, int to, int w)
{
    a[++cnt].to = to;
    a[cnt].w = w;
    a[cnt].pre = head[from];
    head[from] = cnt;
}

bool bfs(int s, int t)///update deep[]
{
    memset(deep, INF, sizeof(deep));
    while(!q.empty())
        q.pop();
    for(int i = 0; i <= n; ++i)
        cur[i] = head[i];
    deep[s] = 0;
    q.push(s);

    while(q.size())
    {
        int first = q.front();
        q.pop();
        for(int i = head[first]; ~i; i = a[i].pre)
        {
            if(deep[ a[i].to ] == INF && a[i].w)///w在此处用来做标记 是正图还是返图
            {
                deep[ a[i].to ] = deep[first] + 1;
                q.push(a[i].to);
            }
        }
    }
    if(deep[t] < INF)
        return 1;
    else
        return 0;
}

int dfs(int now, int t, int limit)
{
    if(!limit || now == t)
        return limit;

    int flow = 0, f;
    for(int i = cur[now]; ~i; i = a[i].pre)
    {
        cur[now] = i;
        if(deep[ a[i].to ] == deep[now] + 1)
            if(f = dfs(a[i].to, t, min(limit, a[i].w)))
            {
                flow += f;
                limit -= f;
                a[i].w -= f;
                a[i^1].w += f;
                if(!limit)
                    break;
            }
    }
    return flow;
}

void Dinic(int s, int t)
{
    while(bfs(s, t))
        maxflow += dfs(s, t, INF);
}

int main()
{
    memset(head, -1, sizeof(head));
    scanf("%lld%lld", &n, &m);
    int start, over, x, y,z;
    scanf("%d%d", &start, &over);
    for(int i = 1; i <= m; ++i)
    {
        scanf("%d%d%d", &x, &y, &z);
        add(x, y, z);
        add(y, x, 0);
    }
    Dinic(start, over);
    cout << maxflow << '\n';
    return 0;
}

果然,涉及DFS的东西,不好理解…

Site by Baole Zhao | Powered by Hexo | theme PreciousJoy