Cod sursa(job #1743889)

Utilizator AlexandruValeanuAlexandru Valeanu AlexandruValeanu Data 18 august 2016 21:32:49
Problema Flux maxim Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 4.45 kb
#include <bits/stdc++.h>

using namespace std;

class PushRelabel
{
private:

    static const int NIL;

    class Edge
    {
    public:

        int flow;
        int capacity;

        int node;
        int next;

        Edge(int _flow, int _capacity, int _node, int _next) : flow(_flow),
            capacity(_capacity), node(_node), next(_next){
        }
    };

    vector<Edge> graph;
    vector<int> head;

    vector<int> excess, height, pointer;
    vector<bool> active;

    vector<int> countHeights;

    queue<int> Q;

    int N;

    void enqueue(int v)
    {
        if (!active[v] && excess[v])
        {
            active[v] = true;
            Q.push(v);
        }
    }

    void push(int u, int p)
    {
        int v = graph[p].node;
        int delta = min(excess[u], graph[p].capacity - graph[p].flow);

        if (height[u] <= height[v] || delta == 0)
            return;

        graph[p].flow += delta;
        graph[p ^ 1].flow -= delta;

        excess[u] -= delta;
        excess[v] += delta;

        enqueue(v);
    }

    void relabel(int u)
    {
        countHeights[height[u]]--;
        height[u] = 2 * N;

        for (int p = head[u]; p != NIL; p = graph[p].next)
        {
            if (graph[p].capacity > graph[p].flow)
                height[u] = min(height[u], height[graph[p].node] + 1);
        }

        countHeights[height[u]]++;
        enqueue(u);
    }

    void discharge(int u)
    {
        bool doneGap = false;

        while (excess[u] > 0)
        {
            if (countHeights[height[u]] == 1 && !doneGap)
            {
                gap(height[u]);
                doneGap = true;
                pointer[u] = NIL;
            }

            if (pointer[u] == NIL)
            {
                relabel(u);
                pointer[u] = head[u];
            }
            else
            {
                int p = pointer[u];
                int v = graph[p].node;

                if (height[u] >= height[v] + 1 && graph[p].capacity > graph[p].flow)
                    push(u, p);
                else
                    pointer[u] = graph[pointer[u]].next;
            }
        }
    }

    void gap(int H)
    {
        for (int i = 0; i < N; ++i)
        {
            if (height[i] >= H)
            {
                countHeights[height[i]]--;
                height[i] = max(height[i], N + 1);
                countHeights[height[i]]++;

                enqueue(i);
            }
        }
    }

    void initPreflow(int S, int T)
    {
        fill(countHeights.begin(), countHeights.end(), 0);
        fill(excess.begin(), excess.end(), 0);
        fill(active.begin(), active.end(), false);
        copy(head.begin(), head.end(), pointer.begin());

        height[S] = N;
        active[S] = active[T] = true;

        countHeights[N] = 1;
        countHeights[0] = N - 1;

        for (int p = head[S]; p != NIL; p = graph[p].next)
        {
            excess[S] += graph[p].capacity;
            push(S, p);
        }
    }

public:

    PushRelabel(int _N) : graph(), head(_N, NIL), excess(_N), height(_N),
        pointer(_N), active(_N), countHeights(2 * _N + 1), Q(), N(_N) {
    }

    void addEdge(int from, int to, int capacity)
    {
        from--; to--;

        graph.push_back(Edge(0, capacity, to, head[from]));
        head[from] = graph.size() - 1;
    }

    void addDoubleEdge(int from, int to, int capacity)
    {
        addEdge(from, to, capacity);
        addEdge(to, from, 0);
    }

    int maximumFlow(int S, int T)
    {
        S--; T--;

        initPreflow(S, T);

        while (!Q.empty())
        {
            int node = Q.front();
            Q.pop();

            active[node] = false;
            discharge(node);
        }

        int flow = 0;

        for (int p = head[S]; p != NIL; p = graph[p].next)
            flow += graph[p].flow;

        return flow;
    }

    vector<int> getSaturated(int node)
    {
        node--;
        vector<int> nodes;

        for (int p = head[node]; p != NIL; p = graph[p].next)
            if (graph[p].flow == graph[p].capacity && graph[p].capacity > 0)
                nodes.push_back(graph[p].node + 1);

        return nodes;
    }
};

const int PushRelabel::NIL = -1;

int main()
{
    ifstream in("maxflow.in");
    ofstream out("maxflow.out");

    int N, M;
    in >> N >> M;

    PushRelabel MF(N);

    for (int i = 0; i < M; ++i)
    {
        int x, y, w;
        in >> x >> y >> w;

        MF.addDoubleEdge(x, y, w);
    }

    out << MF.maximumFlow(1, N) << endl;

    return 0;
}