Cod sursa(job #3193593)

Utilizator SabinaEEnache Sabina-Anca SabinaE Data 14 ianuarie 2024 23:20:03
Problema Cc Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.15 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <queue>
#include <climits>

using namespace std;

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

int main()
{
    int n, suma = 0;
    f >> n;
    int last = 2*n+1;

    vector<vector<int>> adj(last + 1, vector <int>());  // lista de adiacenta - pt bfs
    vector<vector<int>> cost(last + 1, vector <int>(last + 1, 0));
    vector<vector<int>> cap(last + 1, vector <int>(last + 1, 0));
    vector<vector<int>> flux(last + 1, vector <int>(last + 1, 0));

    for (int e = 1; e <= n; e++)
        for (int c = n + 1; c <= 2 * n; c++)
        {
            int cst;
            f >> cst;
            cost[e][c] = cst;
            cost[c][e] = -cst; // in caz ca trebuie sa ne intoarcem
            adj[e].push_back(c);
            adj[c].push_back(e);
            cap[e][c] = 1;
        }

    for (int e = 1; e <= n; e++)
    {
        adj[e].push_back(0);
        adj[0].push_back(e);
        cap[0][e] = 1;
    }

    for (int c = n + 1; c <= 2 * n; c++)
    {
        adj[c].push_back(last);
        adj[last].push_back(c);
        cap[c][last] = 1;
    }

    //bellman ford
    bool drum = true;
    while(drum)
    {
        drum = false;
        queue <int> q;
        vector <int> parinte(last + 1); // tinem parintele fiecarui nod, daca muchia intoarce flux => -parinte
        vector <int> cost_temp(last + 1, INT_MAX); // costuri pt bellman-ford
        for (int i = 0; i <= last; i++)
            parinte[i] = i;

        q.push(0);
        cost_temp[0] = 0;
        while (!q.empty())
        {
            int nod = q.front();
            q.pop();
            for (int i = 0; i < adj[nod].size(); i++)
            {
                int vecin = adj[nod][i];
                if (cap[nod][vecin] > flux[nod][vecin] && cost_temp[vecin] > cost_temp[nod] + cost[nod][vecin])
                {
                    q.push(vecin);
                    parinte[vecin] = nod;
                    cost_temp[vecin] = cost_temp[nod] + cost[nod][vecin];
                    if (vecin == last) // am ajuns la destinatie
                    {
                        drum = true;
                        break;
                    }
                }
            }
        }

        // daca avem drum
        if (drum)
        {
            // parcurgem invers
            int nod = last;
            int flux_max = INT_MAX;
            while (nod != 0)
            {
                int tata = parinte[nod];
                flux_max = min(flux_max,cap[tata][nod] - flux[tata][nod]);
                nod = tata;
            }
            nod = last;
            while (nod != 0)
            {
                int tata = parinte[nod];
                flux[tata][nod] += flux_max;
                flux[nod][tata] -= flux_max;
                nod = tata;
            }
        }
    }

    //ce muchii am folosit pentru costul lor
    for (int e = 1; e <= n; e++)
        for (int c = n + 1; c <= 2 * n; c++)
            if (flux[e][c])
            {
                suma += cost[e][c];
                continue;
            }

    g << suma;
    return 0;
}