Cod sursa(job #1709307)

Utilizator lookingForAChallengeUBB Cociorva Popoveniuc Salajan lookingForAChallenge Data 28 mai 2016 11:45:15
Problema Tribut Scor 100
Compilator cpp Status done
Runda ONIS 2016 - Runda - 2 - ACM ICPC Romanian Programming Contest Marime 2.72 kb
#include <bits/stdc++.h>

using namespace std;

#define ll long long
#define ld long double
#define pb push_back
#define mp make_pair
#define pii pair<int, int>
#define pll pair<ll, ll>
#define pdd pair<ld, ld>
#define all(x) (x).begin(), (x).end()
#define fi first
#define se second

const int NMAX = 210;
const int INF = 1 << 30;

int t, n, m, source, dest;
int a[NMAX], sz[NMAX], b[NMAX];
int cap[NMAX][NMAX], flow[NMAX][NMAX];
int f[NMAX];
vector<int> u[NMAX], v[NMAX];
bitset<NMAX> viz;
deque<int> q;

void reset() {
    memset(a, 0, sizeof(a));
    memset(sz, 0, sizeof(sz));
    memset(b, 0, sizeof(b));
    memset(cap, 0, sizeof(cap));
    memset(flow, 0, sizeof(flow));
    memset(f, 0, sizeof(f));

    for (int i = 0; i < NMAX; i++) {
        u[i].clear();
        v[i].clear();
    }
}

bool bfs() {
    memset(f, 0, sizeof(f));
    viz = 0;
    q.pb(source);
    viz[source] = 1;
    f[source] = source;

    while (!q.empty()) {
        int x = q.front();
        q.pop_front();

        if (x == dest)
            continue;

        for (auto it : v[x]) {
            if (!viz[it] && flow[x][it] < cap[x][it]) {
                viz[it] = 1;
                f[it] = x;
                q.pb(it);
            }
        }
    }

    if (viz[dest])
        return 1;
    return 0;
}

int main() {
    cin.sync_with_stdio(false);

    freopen("tribut.in", "r", stdin);
    freopen("tribut.out", "w", stdout);

    cin >> t;

    for (; t; t--) {
        cin >> n >> m;
        reset();

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

        for (int i = 1; i <= m; i++) {
            cin >> sz[i] >> b[i];
            for (int j = 1; j <= sz[i]; j++) {
                int x;
                cin >> x;
                u[x].pb(i);
            }
        }

        source = 0;
        dest = n + m + 1;

        for (int i = 1; i <= n; i++) {
            v[source].pb(i);
            cap[source][i] = a[i];
        }

        for (int i = 1; i <= n; i++) {
            for (auto it : u[i]) {
                v[i].pb(it + n);
                v[it + n].pb(i);
                cap[i][it + n] = INF;
            }
        }

        for (int i = 1; i <= m; i++) {
            v[i + n].pb(dest);
            cap[i + n][dest] = b[i];
        }

        int max_flow = 0;
        while (bfs()) {
            int x = dest;
            int add = INF;

            while (f[x] != x) {
                add = min(add, cap[f[x]][x] - flow[f[x]][x]);
                x = f[x];
            }

            x = dest;
            while (f[x] != x) {
                flow[f[x]][x] += add;
                flow[x][f[x]] -= add;
                x = f[x];
            }

            max_flow += add;
        }

        cout << max_flow << '\n';
    }

    return 0;
}