Cod sursa(job #1712618)

Utilizator CTI_KnightCir Constantin CTI_Knight Data 3 iunie 2016 09:49:26
Problema Cc Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.98 kb
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>

using namespace std;

int N, G[300][300]; // Retinem graful
int l[300], r[300]; // Suma valorilor adaugate pe o anumita linie / scazuta de pe o anumita coloana
int p[300];     // daca este taietura
int cr[300], cc[300];   // linie / coloana acoperita
int vr[300], vc[300];   // Cu cine este cuplata o anumita linie / coloana
int sum = 0;

void gaseste_zero () {

    int i, j, minim, t;
    for ( minim = 1 << 30, i = 1; i <= N; ++ i )
        if ( !cr[i] )
            for ( j = 1;j <= N; ++ j )
                if ( !cc[j] )
                    minim = min( minim, G[i][j] + vr[i] - vc[j] );
    for ( i = 1; i <= N; ++ i )
        if ( cr[i] )
            vr[i] += minim;
    for ( j = 1; j <= N; ++ j )
        if ( !cc[j] )
            vc[j] += minim;
    for ( i = 1; i <= N; ++ i )
        if ( !cr[i] )
            for ( j = 1; j <= N; ++ j )
                if ( !cc[j] && G[i][j] + vr[i] == vc[j] )
                    if ( r[i] ) {
                        p[i] = j;
                        cr[i] = 1;
                        cc[r[i]] = 0;
                        //sum += G[i][j];
                        break;
                    }
                    else {
                        do {
                            t = l[j];
                            r[i] = j;
                            l[j] = i;
                            i = t;
                            j = p[i];
                        } while( t );
                    return;
                  }
    gaseste_zero();
}

void umple_cu_zero() {
    for ( int i = 0; i < 300; ++ i ) vr[i]=0;
    for ( int i = 0; i < 300; ++ i ) vc[i]=0;
    for ( int i = 0; i < 300; ++ i ) l[i]=0;
    for ( int i = 0; i < 300; ++ i ) r[i]=0;
    for ( int i = 0; i < N; ++ i ) {
        memset( cr, 0, sizeof( cr ) );
        memset( p, 0, sizeof( p ) );
        memcpy( cc, l, sizeof( cc ) );
        gaseste_zero();
    }
}

void citire() {
    scanf( "%d", &N );
    for ( int i = 1; i <= N; ++ i )
    for ( int j = 1; j <= N; ++ j )
        scanf( "%d", &G[i][j] );
}

void afisare() {

    printf("\n");
    for ( int i = 1; i < 300; ++ i )
        if( l[i] != 0 )
            printf( "Cuplaj %i - %i \n", i, l[i] );
    printf( "\n\n" );
    for ( int i = 1; i < 300; ++ i )
        if ( cr[i] != 0 )
            printf( "Linia %i este acoperita \n", i );
    printf("\n\n");
    for ( int i = 1; i < 300; ++ i )
        if ( cc[i] != 0 )
            printf( "Coloana %i este acoperita \n", i );
    printf("\n\n");
    for ( int i = 1; i < 300; ++ i )
        if( p[i] != 0 )
            printf( " (%i, %i) este taiat\n", i, p[i] );
 }

int main()
{
    freopen( "cc.in", "r", stdin );
    freopen( "cc.out", "w", stdout );

    citire();
    umple_cu_zero();
    //afisare();
     for ( int i = 1; i < 300; ++ i )
        if( l[i] != 0 )
            sum += G[l[i]][i];
    cout << sum;

    return 0;
}