kyopro_library

This documentation is automatically generated by online-judge-tools/verification-helper

View the Project on GitHub dyktr06/kyopro_library

:heavy_check_mark: Dinic's Algorithm
(lib/graph/dinic.hpp)

Dinic’s Algorithm

概要

グラフについて、最大流を求めます。

使い方

計算量

以降は、頂点数を $V$、追加された辺の数を $E$ とします。

Verified with

Code

#pragma once

/**
 * @brief Dinic's Algorithm
 * @docs docs/graph/dinic.md
 */

template<typename T>
struct Dinic{
private:
    int V;
    vector<int> level, iter;

    void bfs(int s, int t){
        fill(level.begin(), level.end(), -1);
        level[s] = 0;
        queue<int> q;
        q.push(s);
        while(!(q.empty())){
            int f = q.front();
            q.pop();
            for(auto &e : G[f]){
                if(e.cap > 0 && level[e.to] < 0){
                    level[e.to] = level[f] + 1;
                    if(e.to == t) return;
                    q.push(e.to);
                }
            }
        }
    }

    T dfs(int v, int t, T f){
        if(v == t){
            return f;
        }
        for(int &i = iter[v]; i < (int) G[v].size(); i++){
            edge &e = G[v][i];
            if(e.cap > 0 && level[v] < level[e.to]){
                T d = dfs(e.to, t, min(f, e.cap));
                if(d > 0){
                    e.cap -= d;
                    e.flow += d;
                    G[e.to][e.rev].cap += d;
                    G[e.to][e.rev].flow -= d;
                    return d;
                }
            }
        }
        return 0;
    }

public:
    struct edge{
        int to, rev;
        T cap, flow = 0;
    };
    vector<vector<edge>> G;

    Dinic(const int n) : V(n), level(n), iter(n), G(n){}

    void add_edge(int from, int to, T cap){
        G[from].push_back({to, (int) G[to].size(), cap});
        G[to].push_back({from, (int) G[from].size() - 1, (T) 0});
    }

    T flow(int s, int t){
        T flow = 0;
        while(true){
            bfs(s, t);
            if(level[t] < 0) return flow;
            fill(iter.begin(), iter.end(), 0);
            T f;
            while((f = dfs(s, t, numeric_limits<T>::max())) > 0){
                flow += f;
            }
        }
    }
};
#line 2 "lib/graph/dinic.hpp"

/**
 * @brief Dinic's Algorithm
 * @docs docs/graph/dinic.md
 */

template<typename T>
struct Dinic{
private:
    int V;
    vector<int> level, iter;

    void bfs(int s, int t){
        fill(level.begin(), level.end(), -1);
        level[s] = 0;
        queue<int> q;
        q.push(s);
        while(!(q.empty())){
            int f = q.front();
            q.pop();
            for(auto &e : G[f]){
                if(e.cap > 0 && level[e.to] < 0){
                    level[e.to] = level[f] + 1;
                    if(e.to == t) return;
                    q.push(e.to);
                }
            }
        }
    }

    T dfs(int v, int t, T f){
        if(v == t){
            return f;
        }
        for(int &i = iter[v]; i < (int) G[v].size(); i++){
            edge &e = G[v][i];
            if(e.cap > 0 && level[v] < level[e.to]){
                T d = dfs(e.to, t, min(f, e.cap));
                if(d > 0){
                    e.cap -= d;
                    e.flow += d;
                    G[e.to][e.rev].cap += d;
                    G[e.to][e.rev].flow -= d;
                    return d;
                }
            }
        }
        return 0;
    }

public:
    struct edge{
        int to, rev;
        T cap, flow = 0;
    };
    vector<vector<edge>> G;

    Dinic(const int n) : V(n), level(n), iter(n), G(n){}

    void add_edge(int from, int to, T cap){
        G[from].push_back({to, (int) G[to].size(), cap});
        G[to].push_back({from, (int) G[from].size() - 1, (T) 0});
    }

    T flow(int s, int t){
        T flow = 0;
        while(true){
            bfs(s, t);
            if(level[t] < 0) return flow;
            fill(iter.begin(), iter.end(), 0);
            T f;
            while((f = dfs(s, t, numeric_limits<T>::max())) > 0){
                flow += f;
            }
        }
    }
};
Back to top page