Cod sursa(job #1709376)

Utilizator CNFBTeamCNFB Udristoiu Linca Dicu CNFBTeam Data 28 mai 2016 12:01:03
Problema Tribut Scor 100
Compilator cpp Status done
Runda ONIS 2016 - Runda - 2 - ACM ICPC Romanian Programming Contest Marime 3.37 kb
#include <cstdio>
#include <bitset>
#include <cstring>
#include <deque>
#include <vector>
#include <algorithm>

const int SIZE = 2e2 + 5;
const int INFI = 0x3f3f3f3f;
const int C1 = 0;
const int C2 = 100;

int start_node, finish_node, n, m, q, x, k, answer, minim;
int capacity[SIZE][SIZE], flow[SIZE][SIZE], father[SIZE];
std::bitset <SIZE> marked; std::vector <int> edge[SIZE]; std::deque <int> my_queue;

inline bool bfs( int start_node, int finish_node ) {
    bool ok = false;
    my_queue.clear(); my_queue.push_back(start_node);
    marked.reset(); marked[start_node] = 1;

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

        std::vector <int> :: iterator it;
        for( it = edge[node].begin(); it != edge[node].end(); it ++ ) {
            int next_node = *it;

            if( !marked[next_node] && flow[node][next_node] < capacity[node][next_node] ) {
                marked[next_node] = 1;
                father[next_node] = node;
                my_queue.push_back(next_node);

                if( next_node == finish_node )
                    ok = true;
            }
        }
        my_queue.pop_front();
    }

    return ok;
}

int main( int argc, const char *argv[] ) {

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

    start_node = SIZE - 1; finish_node = SIZE - 2;

    scanf( "%d", &q );
    for( int t = 1; t <= q; t ++ ) {
        scanf( "%d %d", &n, &m );

        for( int i = 1; i <= n; i ++ ) {
            scanf( "%d", &x );
            capacity[i + C2][finish_node] = x;

            edge[i + C2].push_back(finish_node);
            edge[finish_node].push_back(i + C2);
        }

        for( int i = 1; i <= m; i ++ ) {
            scanf( "%d %d", &k, &x );
            capacity[start_node][i + C1] = x;

            edge[start_node].push_back(i + C1);
            edge[i + C1].push_back(start_node);

            for( int j = 1; j <= k; j ++ ) {
                scanf( "%d", &x );
                capacity[i + C1][x + C2] = INFI;

                edge[i + C1].push_back(x + C2);
                edge[x + C2].push_back(i + C1);
            }
        }

        while( bfs(start_node, finish_node) ) {
            std::vector <int> :: iterator it;

            for( it = edge[finish_node].begin(); it != edge[finish_node].end(); it ++ ) {
                int aux_node = *it;

                if( marked[aux_node] && flow[aux_node][finish_node] < capacity[aux_node][finish_node] ) {
                    minim = capacity[aux_node][finish_node] - flow[aux_node][finish_node];

                    for( int node = aux_node; node != start_node; node = father[node] )
                        minim = std::min( minim, capacity[ father[node] ][node] - flow[ father[node] ][node] );

                    answer += minim;
                    flow[aux_node][finish_node] += minim;
                    flow[finish_node][aux_node] -= minim;

                    for( int node = aux_node; node != start_node; node = father[node] ) {
                        flow[ father[node] ][node] += minim;
                        flow[node][ father[node] ] -= minim;
                    }
                }
            }
        }

        printf( "%d\n", answer );

        answer = 0;
        memset( capacity, 0, sizeof(capacity) );
        memset( flow, 0, sizeof(flow) );

        for( int i = 0; i < SIZE; i ++ )
            edge[i].resize(0);
    }

    return 0;
}