Cod sursa(job #371538)

Utilizator MariusMarius Stroe Marius Data 5 decembrie 2009 18:28:44
Problema Cuplaj maxim de cost minim Scor Ascuns
Compilator cpp Status done
Runda Marime 2.77 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
using namespace std;

const char iname[] = "cmcm.in";
const char oname[] = "cmcm.out";

#define MAXN  605

vector < pair < pair <int, int>, pair <int, int> > > edges;

int capacity[MAXN][MAXN], flow_cost;

int getAugmentation(int n, int src, int dst) {
    const int inf = 0x3f3f3f3f;
    vector < pair < pair <int, int>, pair <int, int> > >::iterator it;
    vector <int> d(n + 1, inf), p(n + 1, -1);

    d[src] = 0;
    for (int i = 1; i < n; ++ i) {
        for (it = edges.begin(); it != edges.end(); ++ it) {
            int x = it->first.first;
            int y = it->first.second;
            int cost = it->second.first;
            if (capacity[x][y] > 0) if (d[x] < inf) if (d[y] > d[x] + cost)
                d[y] = d[x] + cost,
                p[y] = x;
        }
    }
    if (p[dst] != -1) {
        flow_cost += d[dst];
        for (int i = dst; i != src; i = p[i])
            capacity[p[i]][i] ^= 1, capacity[i][p[i]] ^= 1;
        return 1;
    }
    return 0;
}

int main(void) {
    ifstream in(iname);
    int cardL, cardR, cardEdges;

    assert(in >> cardL >> cardR >> cardEdges);
    assert(1 <= cardL && cardL <= 300);
    assert(1 <= cardR && cardR <= 300);
    assert(1 <= cardEdges && cardEdges <= 50000);
    int source = 0;
    int sink = cardL + cardR + 1;
    for (int i = 0; i < cardEdges; ++ i) {
        int x, y, cost;
        in >> x >> y >> cost;
        edges.push_back(make_pair(make_pair(x, y + cardL), make_pair(cost, i)));
        capacity[x][y + cardL] = 1;
        edges.push_back(make_pair(make_pair(y + cardL, x), make_pair(-cost, i)));
    }
    for (int i = 1; i <= cardL; ++ i)
        edges.push_back(make_pair(make_pair(source, i), make_pair(0, -1))),
        capacity[source][i] = 1;
    for (int j = 1; j <= cardR; ++ j)
        edges.push_back(make_pair(make_pair(j + cardL, sink), make_pair(0, -1))),
        capacity[j + cardL][sink] = 1;

    while (getAugmentation(cardL + cardR + 2, source, sink)) ;

    vector < pair < pair <int, int>, pair <int, int> > >::iterator it;
    vector <int> r_edges;
    int r_flow_cost = 0;
    for (it = edges.begin(); it != edges.end(); ++ it) {
        int x = it->first.first;
        int y = it->first.second;
        if (1 <= x && x <= cardL) if (1 <= y - cardL && y - cardL <= cardR)
            if (capacity[x][y] == 0)
                r_edges.push_back(it->second.second),
                r_flow_cost += it->second.first;
    }
    assert(flow_cost == r_flow_cost);

    ofstream out(oname);
    out << r_edges.size() << " " << r_flow_cost << "\n";
    for (int i = 0; i < r_edges.size(); ++ i)
        out << r_edges[i] + 1 << " ";
    in.close();
    return 0;
}