Cod sursa(job #886183)

Utilizator vendettaSalajan Razvan vendetta Data 22 februarie 2013 18:07:14
Problema Cc Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.74 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
#include <set>
#include <queue>
#include <deque>

using namespace std;

ifstream f("cc.in");
ofstream g("cc.out");

#define nmax 102*2
#define ll long long
#define inf (1<<30)

int n, cost[nmax][nmax], capac[nmax][nmax], flux[nmax][nmax];
int t[nmax], dist[nmax];
vector<int> gf[nmax];
bool viz[nmax];
int q[nmax*nmax*nmax];

void citeste(){
    f >> n;
    int x,y;
    for(int i=1; i<=n; ++i){
        for(int j=1; j<=n; ++j){
            x = i; y = j + n;
            gf[x].push_back(y);
            gf[y].push_back(x);
            f >> cost[x][y];
            cost[y][x] = -cost[x][y];
            capac[x][y] = 1;
        }
    }
}

void bagaS(int S){
    // bag muchii de genul S -> i; nodurile fiind din priam multime
    for(int i=1; i<=n; ++i){
        gf[S].push_back(i);
        gf[i].push_back(S);
        capac[S][i] = 1;
    }
}

void bagaD(int D){
    // muchie de genul i-> D; nodurile fiind din a 2 multime
    for(int i=n+1; i<=2*n; ++i){
        gf[i].push_back(D);
        gf[D].push_back(i);
        capac[i][D] = 1;
    }
}

inline int Bf(int S, int D){
    for(int i=0; i<=D; ++i) t[i] = 0, viz[i] = 0, dist[i] = inf;
    int st = 1; int dr = 0;
    q[++dr] = S; viz[S] = 1;
    dist[S] = 0;
    for(; st<=dr; ){
        int nod = q[st]; ++st;
        viz[nod] = 0;// l-am scos
        for(int i=0; i<gf[nod].size(); ++i){
            int vc = gf[nod][i];
            if ( capac[nod][vc] > flux[nod][vc] && dist[vc] > dist[nod] + cost[nod][vc] ){
                dist[vc] = dist[nod] + cost[nod][vc];
                t[vc] = nod;
                if (viz[vc] == 0){
                    viz[vc] = 1;
                    q[++dr] = vc;
                }
            }
        }
    }
    return dist[D];
}

void rezolva(){
    // fac un graf bipartit dupa care nodurile din a 2 -a multimea le reindexez si bag un cuplaj maxim de cost minim
    // bag sursa si destinatia
    int S = 0; int D = n *2 + 1;
    bagaS(0); bagaD(n*2+1);

    int CostMin = 0;
    for(int ok=1; ok==1;){
        int CostDrum = Bf(S, D); if (CostDrum == inf) break;// daca nu am reusit sa ajung in destinatie
        // aleg fluxil minim pe care il pot baga pe drumu curent
        int Min = inf;
        for(int i=D; i!=S; i=t[i]){
            // vreau sa bag pe t[i]->i;
            Min = min(Min, capac[ t[i] ][i] - flux[ t[i] ][i]);
        }
        for(int i=D; i!=S; i=t[i]){
            flux[ t[i] ][i] += Min;
            flux[i][ t[i] ] -= Min;
        }
        CostMin += CostDrum;
    }
    cout << CostMin << "\n";
    g << CostMin << "\n";
}

int main(){
    citeste();
    rezolva();

    f.close();
    g.close();

    return 0;
}