Cod sursa(job #3036893)

Utilizator ArseniuVictorStefanArseniu Victor Stefan ArseniuVictorStefan Data 25 martie 2023 11:12:28
Problema Flux maxim Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.71 kb
#include <stdio.h>

int min(int x, int y)
{
    return x <= y ? x : y;
}

// performs Edmonds-Karp algorithm on a graph
struct EdmondsKarp
{
    // the max. no. of edges and nodes
    static const int EDGE_COUNT = 5000;
    static const int NODE_COUNT = 1000;

    // no node / no edge
    static const int NONE = -1;

    // infinity
    static const int INF = 0x3f3f3f3f;

    // the edges of the graph
    struct
    {
        int v;
        int capacity;
        int next;
    } edges[2 * EDGE_COUNT];

    // the first edge of each node
    int begin[NODE_COUNT];

    // for each node, the edge to its parent in the BFS tree
    int to_parent[NODE_COUNT];

    // the no. of nodes and no. of edges
    int n, m;

    // the source and the sink
    int source, sink;

    // inits the graph with _n nodes and the given source and sink
    void init(int _n, int _source, int _sink)
    {
        n = _n;
        m = 0;
        source = _source;
        sink = _sink;
        for(int i = 0; i < n; i++)
            begin[i] = NONE;
    }

    // adds an edge from u to v with the given capacity
    void add_edge(int u, int v, int capacity)
    {
        edges[m] = { v, capacity, begin[u] };
        begin[u] = m++;

        edges[m] = { u, 0, begin[v] };
        begin[v] = m++;
    }

    // BFS to find augmenting paths
    bool bfs()
    {
        static int queue[NODE_COUNT];

        // init the parent edges
        for(int i = 0; i < n; i++)
            to_parent[i] = NONE;
        to_parent[source] = INF;

        // init the queue
        int qfront = 0, qtop = 0;
        queue[qtop++] = source;

        // while the queue isn't empty and no path was found, propagate
        while(qfront < qtop && to_parent[sink] == NONE)
        {
            int u = queue[qfront++];
            for(int i = begin[u]; i != NONE; i = edges[i].next)
            {
                int v = edges[i].v;
                if(edges[i].capacity != 0 && to_parent[v] == NONE)
                {
                    queue[qtop++] = v;
                    to_parent[v] = (i ^ 1);
                }
            }
        }

        // return whether or not a path was found
        return to_parent[sink] != NONE;
    }

    // augment the path according to the BFS tree found
    int augment()
    {
        int flow = INF;
        int v = sink;

        // move back and calculate the flow
        while(v != source)
        {
            int i = to_parent[v];
            flow = min(flow, edges[i ^ 1].capacity);
            v = edges[i].v;
        }

        if(flow == 0)
            return flow;

        // apply the flow
        v = sink;
        while(v != source)
        {
            int i = to_parent[v];
            edges[i].capacity += flow;
            edges[i ^ 1].capacity -= flow;
            v = edges[i].v;
        }

        return flow;
    }

    // finds the max flow in the graph
    int max_flow()
    {
        int flow = 0;

        // while there are augmenting paths found
        while(bfs())
        {
            for(int i = begin[sink]; i != NONE; i = edges[i].next)
                if(edges[i ^ 1].capacity != 0 && to_parent[edges[i].v] != NONE)
                {
                    to_parent[sink] = i;
                    flow += augment();
                }
        }

        return flow;
    }
};

EdmondsKarp flow;

int main()
{
    freopen("maxflow.in", "r", stdin);
    freopen("maxflow.out", "w", stdout);

    // read the graph
    int n, m;
    scanf("%d %d", &n, &m);
    flow.init(n, 0, n - 1);
    for(int i = 0; i < m; i++)
    {
        int u, v, capacity;
        scanf("%d %d %d", &u, &v, &capacity);
        u--; v--;

        flow.add_edge(u, v, capacity);
    }

    // calculate and print the flow
    printf("%d\n", flow.max_flow());
    return 0;
}