Cod sursa(job #1734716)

Utilizator Andrei1998Andrei Constantinescu Andrei1998 Data 27 iulie 2016 23:52:30
Problema Algola Scor 30
Compilator cpp Status done
Runda Arhiva de probleme Marime 4.21 kb
#include <fstream>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
#include <utility>
#include <cassert>

using namespace std;

template <const int NMAX, const int MMAX>
class MaxFLow {
public:
    MaxFLow() {}

    void setN(int _n) { n = _n; }
    void setS(int _s) { s = _s; }
    void setT(int _t) { t = _t; }

    void clear() {
        m = 0;
        for (int i = 1; i <= n; ++ i)
            graph[i].clear();
    }

    void reset() {
        for (int i = 1; i <= m; ++ i)
            edges[i].flow = 0;
    }

    void addEdge(int from, int to, int cap) {
        edges[m ++] = Edge(from, to, 0, cap);
        edges[m ++] = Edge(to, from, 0, 0);

        graph[from].push_back(m - 2);
        graph[to].push_back(m - 1);
    }

    int computeFlow() {
        return Dinic();
    }

private:
    struct Edge {
        int from, to;
        int flow, cap;

        Edge(int _from = 0, int _to = 0, int _flow = 0, int _cap = 0):
            from(_from), to(_to), flow(_flow), cap(_cap) {}
        inline int other(int node) {
            return from ^ to ^ node;
        }
    };

    int n, m, s, t;

    vector <int> graph[NMAX];
    Edge edges[2 * MMAX];

    int father[NMAX];
    bool vis[NMAX];
    queue <int> _queue;

    bool bfs() {
        memset(vis, 0, (n + 1) * sizeof(bool));

        vis[s] = true;
        _queue.push(s);

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

            for (auto it: graph[node])
                if (!vis[edges[it].other(node)] && edges[it].flow < edges[it].cap) {
                    father[edges[it].other(node)] = it;
                    vis[edges[it].other(node)] = true;
                    _queue.push(edges[it].other(node));
                }
        }

        return vis[t];
    }

    int Dinic() {
        int flow = 0;
        while (bfs()) {
            for (auto it: graph[t])
                if (edges[it ^ 1].flow < edges[it ^ 1].cap) {
                    int node = edges[it ^ 1].other(t);
                    int minimum = edges[it ^ 1].cap - edges[it ^ 1].flow;

                    while (node != s) {
                        minimum = min(minimum, edges[father[node]].cap - edges[father[node]].flow);
                        node = edges[father[node]].other(node);
                    }

                    node = edges[it ^ 1].other(t);
                    edges[it ^ 1].flow += minimum;
                    edges[it].flow -= minimum;
                    flow += minimum;

                    while (node != s) {
                        edges[father[node]].flow += minimum;
                        edges[father[node] ^ 1].flow -= minimum;

                        node = edges[father[node]].other(node);
                    }
                }
        }

        return flow;
    }
};


const int TMAX = 5 * 105;
const int NMAX = 50 * TMAX + 5;
const int MMAX = 300 * TMAX + 5;

MaxFLow <NMAX, MMAX> f;

int n, m, s, t;
int members[55];
int sum;

pair <pair <int, int>, int> edges[305];

int pos;
void addFirstLayer() {
    f.setS(s = 1);
    f.setT(t = 2);

    pos = 2;
    for (int i = 1; i <= n; ++ i)
        f.addEdge(s, pos + i, members[i]);

    f.addEdge(pos + 1, t, 50);
    pos += n;

    f.setN(pos);
}

bool addLayer() {
    for (int i = 1; i <= m; ++ i) {
        f.addEdge(pos - n + edges[i].first.first, pos + edges[i].first.second, edges[i].second);
        f.addEdge(pos - n + edges[i].first.second, pos + edges[i].first.first, edges[i].second);
    }

    for (int i = 1; i <= n; ++ i)
        f.addEdge(pos - n + i, pos + i, 50);

    f.addEdge(pos + 1, t, 50);
    pos += n;

    f.setN(pos);

    sum -= f.computeFlow();
    return !sum;
}

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

    cin >> n >> m;

    for (int i = 1; i <= n; ++ i) {
        cin >> members[i];
        sum += members[i];
    }

    int a, b, c;
    for (int i = 1; i <= m; ++ i)
        cin >> edges[i].first.first >> edges[i].first.second >> edges[i].second;

    if (members[1] == sum) {
        cout << "0\n";
        return 0;
    }

    addFirstLayer();

    int timp = 1;
    while (!addLayer()) {
        assert(timp <= 105);
        ++ timp;
    }

    cout << timp << '\n';
    return 0;
}