Cod sursa(job #3190260)

Utilizator TirilaPatricTirila Patric-Gabriel TirilaPatric Data 7 ianuarie 2024 13:44:26
Problema Cc Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.74 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <queue>
#include <climits>

using namespace std;

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

int N, S, T, dist;
vector<vector<int>> list, cap, flow, distanta;
vector<int> previous, distantaMin;
int res;

void citire_date () {
    f>>N;
    T = 2*N+1;
    previous.resize(T+1);
    distantaMin.resize(T+1);
    list.resize(T+1, {});
    cap.assign(T+1, vector<int>(T+1, 0));
    flow.resize(T+1, vector<int>(T+1, 0));
    distanta.resize(T+1, vector<int>(T+1, 0));

    for (int i=1; i<=N; i++) {
        list[0].push_back(i);
        list[i].push_back(0);
        cap[0][i] = 1;

        for (int j=1; j<=N; j++) {
            f>>dist;
            list[i].push_back(j+N);
            list[j+N].push_back(i);
            cap[i][j+N] = 1;
            distanta[i][j+N] = dist;
            distanta[j+N][i] = -dist;
        }
    }

    for (int i=1; i<=N; i++) {
        list[i+N].push_back(T);
        list[T].push_back(i+N);
        cap[i+N][T] = 1;
    }
}

void init_previous () {
    for (int i=0; i<=T; i++) {
        previous[i] = -1;
        distantaMin[i] = INT_MAX;
    }
    distantaMin[0] = 0;
}

int bfs () {
    // gasim un drum de la S la T

    init_previous();
    queue<pair<int, int>> q;
    q.push({0, INT_MAX});

    while (!q.empty()) {
        int cur = q.front().first, minFlowUntilNow = q.front().second;
        q.pop();
        for (auto& next : list[cur]) {

            if (distantaMin[next] > distantaMin[cur] + distanta[cur][next] && cap[cur][next] > flow[cur][next]) {
                previous[next] = cur;
                int residual_cap = cap[cur][next] - flow[cur][next];
                int nextMinFlow = residual_cap > minFlowUntilNow ? minFlowUntilNow : residual_cap;
                distantaMin[next] = distantaMin[cur] + distanta[cur][next];
                q.push({next, nextMinFlow});

//                if (next == T) {
//                    return 1;
//                }
            }
        }
    }

    return previous[T] >= 0;
}

void edmonds_karp () {
    while (true) {
        int flow_of_path = bfs();

        if (!flow_of_path) break; // nu a fost gasit niciun augmented path (de la S la T)

        // in cazul in care a fost gasit, refacem drumul si updatam flow-ul pe tot drumul
        int cur = T;
        while (cur != 0) {
            int prevNode = previous[cur];
            flow[prevNode][cur] += flow_of_path;
            flow[cur][prevNode] -= flow_of_path;
            cur = prevNode;
        }

        res += distantaMin[T];
    }
    g << res;
}

void rezolvare () {
    citire_date();
    edmonds_karp();
}

int main () {
    rezolvare();
    return 0;
}