Cod sursa(job #1111235)

Utilizator toranagahVlad Badelita toranagah Data 18 februarie 2014 18:43:58
Problema Algola Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.24 kb
//Problem algola from Infoarena
#include <cmath>
#include <cstdint>
#include <cassert>

#include <algorithm>
#include <fstream>
#include <iostream>
#include <string>
#include <queue>
#include <vector>
using namespace std;

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

const int16_t INF = 1 << 14;
const int MAX_K = 55;
const int MAX_N = 5505;

int N, M, K;
vector<pair<int, int>> edges[MAX_K];
vector<int> graph[MAX_N];
int16_t cap[MAX_N][MAX_N];
int16_t flow[MAX_N][MAX_N];
int source, sink;
int maxflow;

void read_input();
void solve();
void find_maxflow();
bool find_augmenting_path(int father[]);
void add_edge(int a, int b, int c);
int hash_node(int n, int c);
void add_flow(int a, int b, int f);
int cp(int a, int b);

int main() {
    read_input();
    solve();
    return 0;
}

void read_input() {
    fin >> N >> M;
    K = 0;

    source = 1;
    sink = 2;
    for (int i = 1, x; i <= N; i += 1) {
        fin >> x;
        K += x;
        add_edge(source, hash_node(i, 1), x);
    }
    add_edge(hash_node(1, 1), sink, INF);

    for (int i = 1, a, b, c; i <= M; i += 1) {
        fin >> a >> b >> c;
        edges[a].push_back(make_pair(b, c));
        edges[b].push_back(make_pair(a, c));
    }
}

void solve() {
    int cost = 1;
    maxflow = 0;

    find_maxflow();
    while (maxflow < K) {
        for (int i = 1; i <= N; i += 1) {
            int node = hash_node(i, cost);
            int higher = hash_node(i, cost + 1);
            add_edge(node, higher, INF);

            for (auto x: edges[i]) {
                add_edge(node, hash_node(x.first, cost + 1), x.second);
            }
        }

        add_edge(hash_node(1, cost + 1), sink, INF);
        cost += 1;
        find_maxflow();
    }

    fout << cost - 1;
}

inline void add_edge(int a, int b, int c) {
    graph[a].push_back(b);
    graph[b].push_back(a);
    cap[a][b] = c;
}

inline int hash_node(int n, int c) {
    return (c * MAX_K + n);
}

inline pair<int, int> dehash_node(int n) {
    return make_pair(n % MAX_K, n / MAX_K);
}

void find_maxflow() {
    int father[MAX_N];
    while (find_augmenting_path(father)) {
        for (auto x: graph[sink]) {
            if (father[x] == 0 || cp(x, sink) == 0) continue;

            int new_flow = cp(x, sink);
            for (int node = x; node != source; node = father[node]) {
                new_flow = min(new_flow, cp(father[node], node));
            }

            if (new_flow == 0) continue;

            add_flow(x, sink, new_flow);
            for (int node = x; node != source; node = father[node]) {
                add_flow(father[node], node, new_flow);
            }
            maxflow += new_flow;
        }
    }
}

bool find_augmenting_path(int father[]) {
    fill(father, father + MAX_N, 0);
    father[source] = source;
    queue<int> q;
    q.push(source);

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

        if (node == sink) return true;

        for (auto next: graph[node]) {
            if (father[next] == 0 && cp(node, next) > 0) {
                father[next] = node;
                q.push(next);
            }
        }
    }
    return false;
}

inline void add_flow(int a, int b, int f) {
    flow[a][b] += f;
    flow[b][a] -= f;
}

inline int cp(int a, int b) {
    return cap[a][b] - flow[a][b];
}