Cod sursa(job #1709391)

Utilizator UNIBUC_Echipa_LachetaBicsi Nitu Velea UNIBUC_Echipa_Lacheta Data 28 mai 2016 12:03:42
Problema Tribut Scor 100
Compilator cpp Status done
Runda ONIS 2016 - Runda - 2 - ACM ICPC Romanian Programming Contest Marime 2.81 kb
#include <cassert>
#include <fstream>
#include <cstring>
#include <queue>
#include <algorithm>
#include <bitset>
#include <ctime>
#include <set>
#include <cmath>
#include <iomanip>
#include <map>
#include <stack>
#include <vector>
#include <bitset>

#include <fstream>

using namespace std;

#define FOR(i, a, n) for (int i = a; i <= n; ++i)
#define ROF(i, n, a) for (int i = n; i >= a; i--)
#define FIT(i, v) for (auto &i : v)
#define pb push_back
#define mp make_pair
#define mt make_touple
#define all(x) (x).begin(), (x).end()
#define fi first
#define se second
#define sz(x) ((int)(x).size())
typedef long long ll;
typedef pair<int,int> pii;
const int mod = 2000003;
const int inf = 1000000;
ll powmod(ll a, ll b) {ll res=1; a %= mod; assert(b >= 0); for(; b; b >>= 1) {if (b & 1) res = res * a % mod; a = a * a % mod;} return res;}

const int N = 300;

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

vector<int> G[N];
int C[N][N], F[N][N];
int d[N], from[N];
bool viz[N];
int nodes, source, sink;
void add_edge(int x, int y, int cap) {
    G[x].push_back(y);
    G[y].push_back(x);
    C[x][y] = cap;
}

bool bfs(int s, int f) {
    for (int i = 1; i <= nodes; ++i) {
        viz[i] = false;
        from[i] = 0;
    }
    viz[s] = true;
    queue<int> Q;
    Q.push(s);
    while (!Q.empty()) {
        int x = Q.front();
        Q.pop();
        for (auto &y : G[x]) {
            if (!viz[y] && C[x][y] != F[x][y]) {
                viz[y] = true;
                from[y] = x;
                Q.push(y);
                if (y == sink)
                    return true;
            }
        }
    }
    return false;
}

int maxflow() {
    int flow = 0;
    while(bfs(source, sink)) {
        int minf = inf;
        for (int i = sink; i != source; i = from[i]) {
            minf = min(minf, C[from[i]][i] - F[from[i]][i]);
        }
        
        flow += minf;
        
        for (int i = sink; i != source; i = from[i]) {
            F[from[i]][i] += minf;
            F[i][from[i]] -= minf;
        }
    }
    return flow;
}

int main() {
    int T;
    fin >> T;
    while (T--) {
        int n, m;
        fin >> n >> m;
        
        for (int i = 1; i <= nodes; ++i) {
            G[i].clear();
            for (int j = 1; j <= nodes; ++j) {
                C[i][j] = F[i][j] = 0;
            }
        }
        
        source = 1;
        sink = 1 + n + m + 1;
        nodes = sink;
        for (int i = 1; i <= n; ++i) {
            int c;
            fin >> c;
            add_edge(source, i+1, c);
        }
        for (int i = 1; i <= m; ++i) {
            int s, c;
            fin >> s >> c;
            add_edge(1+n+i, sink, c);
            for (int j = 1; j <= s; ++j) {
                int x;
                fin >> x;
                add_edge(1+x, 1+n+i, inf);
            }
        }
        fout << maxflow() << "\n";
    }
}