Cod sursa(job #2696880)

Utilizator ReksioCroftOctavian Florin Staicu ReksioCroft Data 17 ianuarie 2021 01:15:27
Problema Cuplaj maxim in graf bipartit Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.63 kb
#include <cstdio>
#include <cassert>
#include <cctype>
#include <vector>
#include <bitset>

class inputParser {

    static const unsigned int buffSize = 1 << 17;
    unsigned int pozBuff;
    FILE* fin;
    unsigned char* buffer;


    void getChar( unsigned char& ch ) {
        if ( pozBuff == buffSize ) {
            pozBuff = 0;
            assert( fread( buffer, sizeof( char ), buffSize, fin ) );
        }
        ch = buffer[ pozBuff++ ];
    }


public:
    explicit inputParser( const char* fileName ) {
        fin = fopen( fileName, "r" );
        assert( fin != nullptr );
        buffer = new unsigned char[buffSize];
        pozBuff = buffSize;
    }


    inputParser( const inputParser& dummy ) = delete;

    inputParser& operator=( const inputParser& dummy ) = delete;


    template < class intType >
    inputParser& operator>>( intType& nr ) {
        int sgn( 1 );
        unsigned char ch;
        nr = 0;
        getChar( ch );
        while ( isdigit( ch ) == 0 && ch != '-' )
            getChar( ch );
        if ( ch == '-' ) {
            sgn = -1;
            getChar( ch );
        }
        while ( isdigit( ch ) != 0 ) {
            nr = nr * 10 + ch - '0';
            getChar( ch );
        }
        nr *= sgn;
        return *this;
    }


    inputParser& operator>>( char& ch ) {
        unsigned char ch2;
        do {
            getChar( ch2 );
        } while ( isgraph( ch2 ) == 0 );
        ch = static_cast<char>(ch2);
        return *this;
    }


    inputParser& operator>>( unsigned char& ch ) {
        getChar( ch );
        do {
            getChar( ch );
        } while ( isgraph( ch ) == 0 );
        return *this;
    }


    ~inputParser() {
        fclose( fin );
        delete[] buffer;
    }

};


class outputParser {

    static const unsigned int buffSize = 1 << 17;
    unsigned int pozBuff;
    FILE* fout;
    unsigned char* buffer;


    void putChar( const unsigned char ch ) {
        if ( pozBuff == buffSize ) {
            pozBuff = 0;
            fwrite( buffer, sizeof( char ), buffSize, fout );
        }
        buffer[ pozBuff++ ] = ch;
    }


public:
    explicit outputParser( const char* fileName ) {
        fout = fopen( fileName, "w" );
        buffer = new unsigned char[buffSize];
        pozBuff = 0;
    }


    outputParser( const outputParser& dummy ) = delete;

    outputParser& operator=( const outputParser& dummy ) = delete;


    template < class intType >
    outputParser& operator<<( intType nr ) {
        if ( nr < 0 ) {
            putChar( '-' );
            nr = -nr;
        }
        int cif[20];
        int pozCif = 0;
        do {
            cif[ pozCif++ ] = nr % 10;
            nr /= 10;
        } while ( nr > 0 );
        while ( pozCif > 0 ) {
            unsigned char ch = cif[ --pozCif ] + '0';
            putChar( ch );
        }
        return *this;
    }

    outputParser& operator<<( char ch ) {
        putChar( ch );
        return *this;
    }

    outputParser& operator<<( unsigned char ch ) {
        putChar( ch );
        return *this;
    }

    ~outputParser() {
        fwrite( buffer, sizeof( char ), pozBuff, fout );
        delete[] buffer;
        fclose( fout );
    }
};


using namespace std;
const int nMax = 10001;
vector< int > v[nMax];
int st[nMax], dr[nMax];
bitset< nMax > viz;
int n, m;

bool cupleaza( int nodSt ) {
    if ( !viz[ nodSt ] ) {  ///pt a evita ciclurile infinite
        viz[ nodSt ] = true;
        for ( auto& i : v[ nodSt ] ) {
            if ( !dr[ i ] ) {
                st[ nodSt ] = i;
                dr[ i ] = nodSt;
                return true;
            }
        }
        ///daca nu am gasit un cuplaj direct, incercam sa schimbam cuplajul altui nod
        for ( auto& i : v[ nodSt ] ) {
            if ( cupleaza( dr[ i ] ) ) {
                st[ nodSt ] = i;
                dr[ i ] = nodSt;
                return true;
            }
        }
    }
    return false;
}

int main() {
    int k, sol( 0 );
    bool ok( true );
    inputParser fin( "cuplaj.in" );
    outputParser fout( "cuplaj.out" );
    fin >> n >> m >> k;
    for ( int i = 0; i < k; i++ ) {
        int a, b;
        fin >> a >> b;
        v[ a ].push_back( b );
    }
    while ( ok ) {
        ok = false;
        for ( int i = 1; i <= n; i++ ) {
            if ( !st[ i ] && cupleaza( i ) ) {
                sol++;
                ok = true;
            }
        }
        if ( ok )   ///doar daca au mai aparut modificari, este o sansa sa se regrupeze niste noduri pt a gasi inca un cuplaj
            viz.reset();
    }
    fout << sol << '\n';
    for ( int i = 1; i <= n; i++ ) {
        if ( st[ i ] )
            fout << i << ' ' << st[ i ] << '\n';
    }
    return 0;
}