Cod sursa(job #2588095)

Utilizator IulianOleniucIulian Oleniuc IulianOleniuc Data 24 martie 2020 14:01:24
Problema Cuplaj maxim de cost minim Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.58 kb
#include <bits/stdc++.h>
using namespace std;

ifstream fin("cmcm.in");
ofstream fout("cmcm.out");

class FlowNetwork {
  private:
    int n, s, t;
    vector<pair<int, int>> edg;
    vector<vector<int>> ad, cap, cst;
    vector<int> pot, dst;

    void bellman() {
        fill(pot.begin(), pot.end(), 1e9);
        pot[s] = 0;
        vector<bool> inQueue(n + 1);
        inQueue[s] = true;

        queue<int> q; q.push(s);
        while (!q.empty()) {
            int node = q.front(); q.pop();
            inQueue[node] = false;
            for (int nghb : ad[node])
                if (cap[node][nghb] && pot[node] + cst[node][nghb] < pot[nghb]) {
                    pot[nghb] = pot[node] + cst[node][nghb];
                    if (!inQueue[nghb]) {
                        q.push(nghb);
                        inQueue[nghb] = true;
                    }
                }
        }
    }

    bool dijkstra(vector<int>& dp, vector<int>& father) {
        fill(dp.begin(), dp.end(), 1e9);
        dp[s] = dst[s] = 0;
        priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;
        pq.emplace(0, s);

        vector<bool> vis(n + 1);
        while (!pq.empty()) {
            int node = pq.top().second; pq.pop();
            if (node != t && !vis[node]) {
                vis[node] = true;
                for (int nghb : ad[node])
                    if (cap[node][nghb] && dp[node] + cst[node][nghb] + pot[node] - pot[nghb] < dp[nghb]) {
                        dp[nghb] = dp[node] + cst[node][nghb] + pot[node] - pot[nghb];
                        father[nghb] = node;
                        dst[nghb] = dst[node] + cst[node][nghb];
                        pq.emplace(dp[nghb], nghb);
                    }
            }
        }
        pot = dst;
        return dp[t] != 1e9;
    }

  public:
    FlowNetwork(int n, int s, int t) :
        n(n), s(s), t(t), ad(n + 1),
        cap(n + 1, vector<int>(n + 1)),
        cst(n + 1, vector<int>(n + 1)),
        pot(n + 1), dst(n + 1) { }

    void addEdge(int x, int y, int z, int t, bool add = false) {
        ad[x].push_back(y);
        ad[y].push_back(x);
        cap[x][y] = z;
        cst[x][y] = +t;
        cst[y][x] = -t;
        if (add) edg.emplace_back(x, y);
    }

    pair<pair<int, int>, vector<int>> matching() {
        pair<pair<int, int>, vector<int>> ans;
        vector<int> dp(n + 1);
        vector<int> father(n + 1);

        bellman();
        while (dijkstra(dp, father)) {
            int flow = 1e9;
            for (int i = t; i != s; i = father[i])
                flow = min(flow, cap[father[i]][i]);
            ans.first.first += flow;
            for (int i = t; i != s; i = father[i]) {
                ans.first.second += flow * cst[father[i]][i];
                cap[father[i]][i] -= flow;
                cap[i][father[i]] += flow;
            }
        }

        for (int i = 0; i < (int) edg.size(); i++)
            if (!cap[edg[i].first][edg[i].second])
                ans.second.push_back(i + 1);
        return ans;
    }
};

int main() {
    int m, n, e; fin >> m >> n >> e;
    FlowNetwork graph(m + n + 2, m + n + 1, m + n + 2);
    for (int i = 1; i <= m; i++)
        graph.addEdge(m + n + 1, i, 1, 0);
    for (int i = 1; i <= n; i++)
        graph.addEdge(m + i, m + n + 2, 1, 0);
    for (int i = 0; i < e; i++) {
        int x, y, z; fin >> x >> y >> z;
        graph.addEdge(x, m + y, 1, z, true);
    }

    auto ans = graph.matching();
    fout << ans.first.first << ' ' << ans.first.second << '\n';
    for (int edge : ans.second)
        fout << edge << ' ';
    fout << '\n';

    fout.close();
    return 0;
}