Cod sursa(job #2643744)

Utilizator ardutgamerAndrei Bancila ardutgamer Data 21 august 2020 12:51:26
Problema Flux maxim Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.28 kb
#include <fstream>
#include <iostream>
#include <vector>
#include <queue>
#include <cstdio>
#include <algorithm>
using namespace std;

const int INF = 2020;

ifstream fin("maxflow.in");
ofstream fout("maxflow.out");

struct Muchie
{
    int de_la, pana_la, cap, flux, poz;
    Muchie(int de_la, int pana_la, int cap, int flux, int poz) :
        de_la(de_la), pana_la(pana_la), cap(cap), flux(flux), poz(poz) {}
};

struct Dinic
{
    int N;
    vector<vector<Muchie> > G;
    vector<Muchie*> tata; /// Ca sa economisesc memoria, altfel ar trebui sa retin muchia ori ceva cu pozitia muchiei in lista de adiacenta

    Dinic(int N) : N(N), G(N), tata(N) {}

    /// Si incepe de la 0
    void PuneMuchia(int de_la, int pana_la, int cap)
    {
        G[de_la].push_back(Muchie(de_la, pana_la, cap, 0, G[pana_la].size()));
        if (de_la == pana_la) G[de_la].back().poz++;
        G[pana_la].push_back(Muchie(pana_la, de_la, 0, 0, G[de_la].size() - 1));
        cin.get();
    }


    /// s = sursa, t = tinta / target
    long long GasesteFluxBlocant(int s, int t)
    {
        fill(tata.begin(), tata.end(), (Muchie*)NULL);
        tata[s] = &G[0][0] - 1; /// aritmetica pe pointeri
        unsigned int x, i;

        queue< int > q;
        q.push(s);
        while (!q.empty())
        {
            x = q.front();
            q.pop();
            for (i = 0; i < G[x].size(); ++i)
            {
                Muchie& e = G[x][i];
                if (!tata[e.pana_la] && e.cap - e.flux > 0)
                {
                    tata[e.pana_la] = &G[x][i];
                    q.push(e.pana_la);
                }
            }
        }

        if (!tata[t]) return 0;


        /// Trimit fluxul cu un DFS. Neoptimizat, nu ma folosesc de nivelurile pe care sunt nodurile
        long long flux_total = 0;
        for (i = 0; i < G[t].size(); ++i)
        {
            /// Folosesc muchiile inverse
            Muchie* start = &G[G[t][i].pana_la][G[t][i].poz];

            int marire_flux = INF;

            Muchie* e = start;
            while (marire_flux > 0 && e != tata[s])
            {
                if (!e)
                {
                    marire_flux = 0;
                    break;
                }
                marire_flux = min(marire_flux, e->cap - e->flux);
                e = tata[e->de_la];
            }

            if (marire_flux == 0)
                continue;

            e = start;
            while (marire_flux > 0 && e != tata[s])
            {
                e->flux += marire_flux;
                G[e->pana_la][e->poz].flux -= marire_flux;
                e = tata[e->de_la];
            }

            flux_total += marire_flux;
        }
        return flux_total;
    }

    long long FluxMaxim(int s, int t)
    {
        long long flux_total = 0;
        while (long long flux = GasesteFluxBlocant(s, t))
            flux_total += flux;
        return flux_total;
    }
};


int main()
{
    int t;
    int n, m;
    fin >> n >> m;
    Dinic D(n);
    int a, b, c;
    int s = 0;
    int tinta = n - 1;
    for (int i = 1; i <= m; i++)
    {
        fin >> a >> b >> c;
        D.PuneMuchia(a-1, b-1, c);
    }
    fout << D.FluxMaxim(s, tinta) << "\n";
    return 0;
}