Cod sursa(job #1729036)

Utilizator StarGold2Emanuel Nrx StarGold2 Data 14 iulie 2016 00:35:58
Problema Algola Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.65 kb
#include <cstdio>
#include <algorithm>
#include <vector>
#include <deque>

static const int DIM = 5e3 + 5;
static const int INF = 100;

std::vector< std::pair<int, int> > IEdge[ DIM ];
std::vector<int> Edge[ DIM ], Father, Marked;
int Capacity[ DIM ][ DIM ], Flow[ DIM ][ DIM ];

bool BFS( int Source, int Destination ) {
    
    std::fill( Father.begin(), Father.end(), 0 );
    std::fill( Marked.begin(), Marked.end(), 0 );
    bool ok = false; Marked[ Source ] = 1;
    
    std::deque<int> MyQueue; MyQueue.push_back( Source );
    
    while( !MyQueue.empty() ) {
        int Node = MyQueue.front();
        
        for( std::vector<int> :: iterator it = Edge[ Node ].begin(); it != Edge[ Node ].end(); it ++ ) {
            int NextNode = *it;

            if( Marked[ NextNode ] || Capacity[ Node ][ NextNode ] == Flow[ Node ][ NextNode ] )
                continue;

            if( NextNode != Destination ) {
                Marked[ NextNode ] = 1; Father[ NextNode ] = Node;
                MyQueue.push_back( NextNode );
            } else
                ok = true;
        }
        
        MyQueue.pop_front();
    }
    
    return ok;
}

void AddFlow( int Source, int Destination, int &MaxFlow ) {

    while( BFS( Source, Destination ) ) {
        for( std::vector<int> :: iterator it = Edge[ Destination ].begin(); it != Edge[ Destination ].end(); it ++ ) {
            int Node = *it;

            if( !Marked[ Node ] || Capacity[ Node ][ Destination ] == Flow[ Node ][ Destination ] )
                continue;

            int Minim = INF; Father[ Destination ] = Node;

            for( int NextNode = Destination; NextNode != Source; NextNode = Father[ NextNode ] )
                Minim = std::min( Minim, Capacity[ Father[ NextNode ] ][ NextNode ] - Flow[ Father[ NextNode ] ][ NextNode ] );

            MaxFlow += Minim;

            for( int NextNode = Destination; NextNode != Source; NextNode = Father[ NextNode ] ) {
                Flow[ Father[ NextNode ] ][ NextNode ] += Minim;
                Flow[ NextNode ][ Father[ NextNode ] ] += Minim;
            }
        }
    }

    return;
}

void AddEdge( int Node1, int Node2, int Cost ) {
    Capacity[ Node1 ][ Node2 ] = Cost;
    Edge[ Node1 ].push_back( Node2 );
    Edge[ Node2 ].push_back( Node1 );
    return;
}

void SolveTestCase( void ) {
    int N, M, X, Y, Z, Source = 0, Destination = DIM - 4;
    int Answer = 0, MaxFlow = 0, Total = 0;

    scanf( "%d %d", &N, &M );
    Father.resize( DIM );
    Marked.resize( DIM );

    for( int i = 1; i <= N; i ++ ) {
        scanf( "%d", &X ); Total += X;
        AddEdge( Source, i, X );
    }

    for( int i = 1; i <= M; i ++ ) {
        scanf( "%d %d %d", &X, &Y, &Z );

        IEdge[ X ].push_back( std::make_pair( Y, Z ) );
        IEdge[ Y ].push_back( std::make_pair( X, Z ) );
    }

    AddEdge( 1, Destination, INF );
    AddFlow( Source, Destination, MaxFlow );

    while( MaxFlow < Total ) {
        Answer ++;

        for( int i = 1; i <= N; i ++ ) {
            AddEdge( i + N * ( Answer - 1 ), i + N * Answer, INF );

            for( std::vector< std::pair<int, int> > :: iterator it = IEdge[ i ].begin(); it != IEdge[ i ].end(); it ++ ) {
                std::pair<int, int> Node = *it;
                AddEdge( i + N * ( Answer - 1 ), Node.first + N * Answer, Node.second );
            }
        }

        AddEdge( 1 + N * Answer, Destination, INF );
        AddFlow( Source, Destination, MaxFlow );
    }

    printf( "%d\n", Answer );
    return;
}

int main( int argc, const char *argv[] ) {
    int T = 1;

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

    for( int i = 1; i <= T; i ++ )
        SolveTestCase();

    return 0;
}