Cod sursa(job #1726027)

Utilizator bciobanuBogdan Ciobanu bciobanu Data 6 iulie 2016 23:59:52
Problema Cuplaj maxim de cost minim Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.64 kb
#include <bits/stdc++.h>

using namespace std;

constexpr int MAX_N = 300;
constexpr int INF = 0x3f3f3f3f;

// to-do overflow?
int adj[MAX_N + 1][MAX_N + 1];
int edgeIndex[MAX_N + 1][MAX_N + 1];
int p[MAX_N + 1];
int way[MAX_N + 1];
int l[MAX_N + 1], r[MAX_N + 1];
int minV[MAX_N + 1];
bool used[MAX_N + 1];
int nodePair[MAX_N + 1];

int main() {
    ifstream cin("cmcm.in");
    ofstream cout("cmcm.out");
    cin.tie(0);
    ios_base::sync_with_stdio(false);
    int n, m, e; cin >> n >> m >> e;

    const bool swapped = (n > m);
    if (swapped) {
        swap(n, m);
    }
    for (int i = 1; i <= n; i += 1) {
        for (int j = 1; j <= m; j += 1) {
            adj[i][j] = INF;
        }
    }

    for (int i = 0; i < e; i += 1) {
        int u, v, cost; cin >> u >> v >> cost;
        if (not(swapped)) {
            adj[u][v] = cost;
            edgeIndex[u][v] = i;
        } else {
            adj[v][u] = cost;
            edgeIndex[v][u] = i;
        }
    }

    for (int i = 1; i <= n; i += 1) {
        p[0] = i;
        int j0 = 0;
        memset(minV, 0x3f, 4 * (m + 1));
        memset(used, 0, m + 1);
        do {
            used[j0] = true;
            int i0 = p[j0], delta = INF, j1;
            for (int j = 1; j <= m; j += 1) {
                if (not(used[j])) {
                    const int option = adj[i0][j] - l[i0] - r[j];
                    if (option < minV[j]) {
                        minV[j] = option;
                        way[j] = j0;
                    }
                    if (minV[j] < delta) {
                        delta = minV[j];
                        j1 = j;
                    }
                }
            }
            for (int j = 0; j <= m; j += 1) {
                if (used[j]) {
                    l[p[j]] += delta;
                    r[j] -= delta;
                } else {
                    minV[j] -= delta;
                }
            }
            j0 = j1;
        } while (p[j0]);
        do {
            int j1 = way[j0];
            p[j0] = p[j1];
            j0 = j1;
        } while (j0);
    }

    for (int i = 1; i <= m; i += 1) {
        nodePair[p[i]] = i;
    }

    int cost = 0;
    int flow = 0;
    for (int i = 1; i <= n; i += 1) {
        if (adj[i][nodePair[i]] != INF) {
            flow += 1;
            cost += adj[i][nodePair[i]];
        }
    }

    cout << flow << ' '
         << cost << '\n';

    for (int i = 1; i <= n; i += 1) {
        if (adj[i][nodePair[i]] != INF) {
            cout << 1 + edgeIndex[i][nodePair[i]] << ' ';
        }
    }
    cout << '\n';

    return 0;
}