Cod sursa(job #2978484)

Utilizator DKMKDMatei Filibiu DKMKD Data 13 februarie 2023 20:07:53
Problema Cuplaj maxim de cost minim Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.04 kb
#include <bits/stdc++.h>

#define MAX_N 300
#define MAX_M 300
#define MAX_VT (MAX_N + MAX_M + 2)
#define MULT (1 << 30)

using namespace std;

int muchie[MAX_VT + 1][MAX_VT + 1];

struct FLOW {
    struct elemPQ {
        int u, cost;

        bool operator < (const elemPQ& a) const {
            return cost > a.cost;
        }
    };

    int s, t, vt;
    int maxFlow, minCost;
    bool inQ[MAX_VT], vis[MAX_VT];
    int cap[MAX_VT][MAX_VT], cost[MAX_VT][MAX_VT], flux[MAX_VT][MAX_VT], parent[MAX_VT], realCost[MAX_VT], newCost[MAX_VT], fakeCost[MAX_VT];
    vector <int> edges[MAX_VT];

    void add_edge(int u, int v, int c, int z) {
        edges[u].push_back(v);
        edges[v].push_back(u);
        cap[u][v] = c;
        cost[u][v] = z;
        cost[v][u] = -z;
    }

    void bellman() {
        int u;
        queue <int> q;

        for (u = 0; u < vt; u++)
            newCost[u] = MULT;
        for (u = 0; u < vt; u++)
            inQ[u] = false;

        newCost[s] = 0;
        q.push(s);
        while (!q.empty()) {
            u = q.front();
            q.pop();
            inQ[u] = false;

            for (int v : edges[u]) {
                if (newCost[u] + cost[u][v] < newCost[v] && flux[u][v] < cap[u][v]) {
                    parent[v] = u;
                    newCost[v] = newCost[u] + cost[u][v];
                    if (!inQ[v]) {
                        q.push(v);
                        inQ[v] = true;
                    }
                }
            }
        }
    }

    bool dijkstra() {
        int u;
        priority_queue <elemPQ> pq;

        for (u = 0; u < vt; u++) {
            parent[u] = -1;
            realCost[u] = newCost[u];
            fakeCost[u] = MULT;
            vis[u] = false;
        }

        newCost[s] = fakeCost[s] = 0;
        pq.push({ s, 0 });
        while (!pq.empty()) {
            u = pq.top().u;
            pq.pop();

            if (!vis[u]) {
                vis[u] = true;
                for (int v : edges[u]) {
                    if (fakeCost[u] + cost[u][v] + realCost[u] - realCost[v] < fakeCost[v] && flux[u][v] < cap[u][v]) {
                        parent[v] = u;
                        fakeCost[v] = fakeCost[u] + cost[u][v] + realCost[u] - realCost[v];
                        newCost[v] = newCost[u] + cost[u][v];
                        pq.push({ v, fakeCost[v] });
                    }
                }
            }
        }

        return fakeCost[t] != MULT;
    }

    void minCostmaxFlow() {
        int newFlow, newCost, v;

        bellman();

        maxFlow = 0;
        minCost = 0;
        while (dijkstra()) {
            newFlow = MULT;
            newCost = 0;
            v = t;
            while (v != s) {
                newFlow = min(newFlow, cap[parent[v]][v] - flux[parent[v]][v]);
                newCost += cost[parent[v]][v];
                v = parent[v];
            }

            maxFlow += newFlow;
            minCost += newFlow * newCost;
            v = t;
            while (v != s) {
                flux[parent[v]][v] += newFlow;
                flux[v][parent[v]] -= newFlow;
                v = parent[v];
            }
        }
    }
};

FLOW cuplaj;

int main() {
    ifstream cin("cmcm.in");
    ofstream cout("cmcm.out");

    int n, m, k, u, v, c;

    cin >> n >> m >> k;
    for (int i = 1; i <= k; i++) {
        cin >> u >> v >> c;
        v += n;
        muchie[u][v] = i;
        cuplaj.add_edge(u, v, 1, c);
    }

    for (u = 1; u <= n; u++)
        cuplaj.add_edge(0, u, 1, 0);
    for (v = n + 1; v <= n + m; v++)
        cuplaj.add_edge(v, n + m + 1, 1, 0);
    cuplaj.s = 0;
    cuplaj.t = n + m + 1;
    cuplaj.vt = n + m + 2;

    cuplaj.minCostmaxFlow();

    cout << cuplaj.maxFlow << " " << cuplaj.minCost << "\n";
    for (u = 1; u <= n; u++) {
        for (v = n + 1; v <= n + m; v++) {
            if (cuplaj.flux[u][v])
                cout << muchie[u][v] << " ";
        }
    }

    return 0;
}