Cod sursa(job #1709570)

Utilizator UPB_Darius_Rares_SilviuPeace my pants UPB_Darius_Rares_Silviu Data 28 mai 2016 12:54:38
Problema Tribut Scor 100
Compilator cpp Status done
Runda ONIS 2016 - Runda - 2 - ACM ICPC Romanian Programming Contest Marime 3.31 kb
#include <cstdio>
#include <algorithm>
#include <queue>
#include <vector>
#define NMAX 209
#define oo (1<<30)
using namespace std;

int N, M, cap[ NMAX ][ NMAX ], flow[ NMAX ][ NMAX ], d[ NMAX ], T[ NMAX ], inQ[ NMAX ], bani[ NMAX ], cash[ NMAX ];
queue<int> Q;
vector<int> G[NMAX];

bool BFS(int S, int D) {
    for (int i = 0; i <= N; ++i) {
        d[ i ] = oo;
        T[ i ] = 0;
        inQ[ i ] = 0;
    }

    d[ S ] = 0;
    T[ S ] = S;
    Q.push( S );
    inQ[ S ] = 1;

    while (!Q.empty()) {
        int node = Q.front();
        Q.pop();
        inQ[ node ] = 0;

        if (node == D) {
            continue;
        }
        for (vector<int>::iterator it = G[node].begin(); it != G[node].end(); ++it) {
            if (d[ node ] + 1 < d[ *it] && flow[ node ][ *it ] < cap[ node ][ *it ]) {
                d[ *it ] = d[ node ] + 1;
                T[ *it ] = node;

                if (!inQ[ *it ]) {
                    inQ[ *it ] = 1;
                    Q.push( *it );
                }
            }
        }
    }

    return T[ D ];
}

int maxflow(int S, int D) {
    int sol = 0;

    while (BFS(S, D)) {
        for (vector<int>::iterator it = G[ D ].begin(); it != G[ D ].end(); ++it) {
            if (T[ *it] && flow[ *it ][ D ] < cap[ *it ][ D ]) {
                T[ D ] = *it;
                int minFlow = oo;
                for (int node = D; node != S; node = T[ node]) {
                    minFlow = min( minFlow, cap[ T[node] ][ node ] - flow[ T[node] ][ node ]);
                }

                if (minFlow > 0) {
                    sol += minFlow;
                    for (int node = D; node != S; node = T[ node]) {
                        flow[ T[node] ][ node ] += minFlow;
                        flow[ node ][ T[node] ] -= minFlow;
                    }
                }
            }
        }
    }

    return sol;
}

void solve() {
    for (int i = 0; i <= N; ++i) {
        for (int j = 0; j <= N; ++j) {
            flow[i][j] = cap[i][j] = 0;
        }
    }
    scanf("%d%d", &N, &M);
    for (int i = 1; i <= N; ++i) {
        scanf("%d", &bani[ i ]);
    }
    for (int a = 1; a <= M; ++a) {
        int p, x, y, c;
        scanf("%d%d", &p, &cash[ a ]);
        for (int i = 1; i <= p; ++i) {
            scanf("%d", &x);
            y = a + N;
            cap[ x ][ y ] = cash[ a ];
            G[ x ].push_back( y );
            G[ y ].push_back( x );

//            printf("++ %d->%d = %d\n", x, y, cap[x][y]);
        }
    }

    for (int i = 1; i <= N; ++i) {
        int x, y, c;
        x = 0;
        y = i;
        c = bani[ i ];
        cap[ x ][ y ] = c;
        G[ x ].push_back( y );
        G[ y ].push_back( x );
//        printf("++ %d->%d = %d\n", x, y, cap[x][y]);
    }


    for (int i = 1; i <= M; ++i) {
        int x, y, c;
        x = i + N;
        y = N + M + 1;

        cap[ x ][ y ] = cash[ i ];
        G[ x ].push_back( y );
        G[ y ].push_back( x );
//        printf("++ %d->%d = %d\n", x, y,cap[x][y]);
    }
    N = N + M + 1;
    printf("%d\n", maxflow(0, N));
}
int main() {
    freopen("tribut.in", "r", stdin);
    freopen("tribut.out", "w", stdout);

    int T;
    scanf("%d", &T);
    while (T--) {
        solve();
    }

    return 0;
}