Cod sursa(job #1255876)

Utilizator j.loves_rockJessica Joanne Patrascu j.loves_rock Data 5 noiembrie 2014 13:56:53
Problema Cuplaj maxim de cost minim Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.21 kb
#include <algorithm>
#include <fstream>
#include <limits>
#include <queue>
#include <utility>
#include <vector>
using namespace std;

const int INF = numeric_limits<int>::max();
const int MAXN = 301;
const int MAXNN = 601;

int capacity[MAXNN][MAXNN], weight[MAXNN][MAXNN], edge_index[MAXN][MAXN];

int bellman_ford(
        const int source,
        const int sink,
        vector<int>& tree,
        const vector<vector<int>>& rG) {
    vector<int> D(rG.size(), INF);
    fill(tree.begin(), tree.end(), -1);
    queue<int> Q;
    vector<bool> inQ(rG.size(), false);

    Q.push(source);
    inQ[source] = true;
    tree[source] = source;
    D[source] = 0;

    while (!Q.empty()) {
        int u = Q.front(); Q.pop();
        inQ[u] = false;

        for (int v : rG[u])
            if (capacity[u][v] && D[v] > D[u] + weight[u][v]) {
                D[v] = D[u] + weight[u][v];
                tree[v] = u;
                if (!inQ[v]) {
                    Q.push(v);
                    inQ[v] = true;
                }
            }
    }
    return D[sink];
}

inline void augmentFlow(
        vector<int>& matching,
        const int flow,
        int v,
        const vector<int>& tree) {
    int nu = matching.size() - 1;
    for (int u = tree[v]; u != v; v = u, u = tree[v]) {
        capacity[u][v] -= flow;
        capacity[v][u] += flow;

        if ((0 < u && u <= nu) && (nu < v && v < tree.size() - 1)) {
            matching[u] = v - nu;
        }
    }
}

pair<int, int> minCostMaxFlow(
        const int source,
        const int sink,
        vector<int>& matching,
        const vector<vector<int>>& rG) {
    int flow = 0, cost = 0;
    vector<int> tree(rG.size());

    while (true) {
        int path_cost = bellman_ford(source, sink, tree, rG);
        if (tree[sink] == -1) break;

        augmentFlow(matching, 1, sink, tree);

        flow++;
        cost += path_cost;
    }
    return make_pair(flow, cost);
}

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

    int NU, NV, edges; fin >> NU >> NV >> edges;
    int source = 0, sink = NU + NV + 1, N = NU + NV + 2;

    // residual graph and residual capacity
    vector<vector<int>> rG(N);

    // necessary because of stupid, stupid output format for this problem :(
    vector<int> matching(NU+1, 0);
    //vector<vector<int>> edge_index(NU+1, vector<int>(NV+1, 0));

    for (int u, v, z, i = 1; edges; --edges, ++i) {
        fin >> u >> v >> z;
        edge_index[u][v] = i;

        v += NU;
        rG[u].push_back(v);      capacity[u][v] = 1;
        rG[v].push_back(u);
        weight[u][v] = z;
        weight[v][u] = -z;
        // add edges in the residual graph to the source and the sink
        rG[source].push_back(u); capacity[source][u] = 1;
        rG[u].push_back(source);
        rG[v].push_back(sink);   capacity[v][sink] = 1;
        rG[sink].push_back(v);
    }

    pair<int, int> result = minCostMaxFlow(source, sink, matching, rG);

    fout << result.first << ' ' << result.second << '\n';
    for (int u = 1; u <= NU; ++u) if (matching[u])
        fout << edge_index[u][matching[u]] << ' ';
    fout << endl;

    return 0;
}