Cod sursa(job #3120873)

Utilizator redstonegamer22Andrei Ion redstonegamer22 Data 9 aprilie 2023 00:53:05
Problema Cuplaj maxim de cost minim Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.7 kb
#include <bits/stdc++.h>

using namespace std;

#ifndef LOCAL
ifstream in("fmcm.in");
ofstream out("fmcm.out");
#define cin in
#define cout out
#endif // LOCAL

struct MCMF {
    struct Edge {
        int from, to, flow, cap, cost;
    };

    static const int buffer = 7;
    int n, source, sink;
    vector<Edge> edges;
    vector<vector<int>> edge_ids;
    vector<int> potential;
    vector<int> coming;

    MCMF(int _n, int _source, int _sink) {
        n = _n; source = _source; sink = _sink;
        edge_ids.resize(n + buffer);
        potential.resize(n + buffer);
        coming.resize(n + buffer);
    }

    void add_edge(int from, int to, int cap, int cost) {
        edge_ids[from].push_back(edges.size()); edges.push_back({from, to, 0, cap, cost});
        edge_ids[to].push_back(edges.size()); edges.push_back({to, from, 0, 0, -cost});
    }

    void bellman_ford() {
        vector<int> dist(n + buffer, 0);

        for(int i = 0; i < n + buffer; i++) {
            for(int i = 0; i < edges.size(); i += 2) {
                const auto& ed = edges[i];
                dist[ed.to] = min(dist[ed.to], dist[ed.from] + ed.cost);
            }
        }

        potential = dist;
    }

    bool dijkstra() {
        const int INF = 1e9;
        vector<int> dist(n + buffer, INF);
        dist[source] = 0;

        priority_queue<pair<int, int>> pq;
        pq.push({-dist[source], source});

        while(!pq.empty()) {
            auto cnt = pq.top(); pq.pop();

            if(dist[cnt.second] != -cnt.first) continue;

            for(auto eid : edge_ids[cnt.second]) {
                const auto &ed = edges[eid];
                if(ed.flow == ed.cap) continue;

                if(dist[ed.to] > dist[ed.from] + (ed.cost + potential[ed.from] - potential[ed.to])) {
                    dist[ed.to] = dist[ed.from] + (ed.cost + potential[ed.from] - potential[ed.to]);
                    coming[ed.to] = eid;
                    pq.push({-dist[ed.to], ed.to});
                }
            }
        }

        potential = dist;
        return dist[sink] != INF;
    }

    int64_t flow = 0, cost = 0;

    void compute() {
        for(auto &e : edges) e.flow = 0;
        flow = 0; cost = 0;

        bellman_ford();

        while(dijkstra()) {
            int cnt_flow = 1e9;

            for(int x = sink; x != source; x = edges[coming[x]].from) {
                cnt_flow = min(cnt_flow, edges[coming[x]].cap - edges[coming[x]].flow);
            }
            flow += cnt_flow;

            for(int x = sink; x != source; x = edges[coming[x]].from) {
                edges[coming[x] ^ 0].flow += cnt_flow;
                edges[coming[x] ^ 1].flow -= cnt_flow;

                cost += 1LL * edges[coming[x]].cost * cnt_flow;
            }
        }
    }

    int64_t max_flow() {
        return flow;
    }

    int64_t min_cost() {
        return cost;
    }

    vector<int> get_caps() {
        vector<int> ret;
        for(auto e : edges) {
            if(e.flow >= 1 && e.cap >= 2) ret.push_back(e.cap - 1);
        }
        return ret;
    }
};

int main() {
    int n, m, e; cin >> n >> m >> e;
    MCMF mcmf(n + m + 5, 1, 1 + n + m + 1);

    for(int i = 1; i <= n; i++) {
        mcmf.add_edge(1, 1 + i, 1, 0);
    }

    for(int i = 2; i <= e + 1; i++) {
        int x, y, cost; cin >> x >> y >> cost;
        mcmf.add_edge(1 + x, 1 + n + y, i, cost);
    }

    for(int i = 1; i <= m; i++) {
        mcmf.add_edge(1 + n + i, 1 + n + m + 1, 1, 0);
    }

    mcmf.compute();
    cout << mcmf.max_flow() << " " << mcmf.min_cost() << '\n';
    for(auto e : mcmf.get_caps()) cout << e << " "; cout << '\n';
}