Cod sursa(job #2072523)

Utilizator EuAlexOtaku Hikikomori EuAlex Data 21 noiembrie 2017 22:08:24
Problema Cuplaj maxim de cost minim Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.54 kb
#include <cstdio>
#include <vector>
#include <queue>
#include <climits>
#include <algorithm>
#include <cstring>
#include <cassert>

using namespace std;

struct Nod {
    int nod, cost;
    bool operator > (Nod other) const {
        return cost > other.cost;
    }
};

struct Muchie {
    int to, rev, flow, cap, cost, ind;
};

int n, m, src, dest;
int prevnode[605], prevedge[605], prevflow[605], dist[605], distdij[605];
bool viz[605];
vector <Muchie> g[605];

void bellmanFord() {
    fill(dist, dist + dest + 1, INT_MAX);
    queue <int> q;
    q.push(src);
    dist[src] = 0;

    while(!q.empty()) {
        int from = q.front();

        for(int k = 0; k < g[from].size(); ++ k) {
            Muchie& e = g[from][k];

            if(e.cap > e.flow && dist[from] + e.cost < dist[e.to]) {
                dist[e.to] = dist[from] + e.cost;
                q.push(e.to);
            }
        }

        q.pop();
    }
}

void dijkstra() {
    fill(distdij, distdij + dest + 1, INT_MAX);
    memset(viz, 0, sizeof(viz));
    priority_queue <Nod, vector<Nod>, greater<Nod>> q;
    q.push({src, 0});
    distdij[src] = 0;
    prevflow[src] = INT_MAX;

    while(!q.empty()) {
        int from = q.top().nod;

        if(viz[from] == 0) {
            viz[from] = 1;

            for(int k = 0; k < g[from].size(); ++ k) {
                Muchie& e = g[from][k];

                int aux = distdij[from] + dist[from] - dist[e.to] + e.cost;

                if(e.flow < e.cap && distdij[e.to] > aux) {
                    distdij[e.to] = aux;
                    q.push({e.to, aux});

                    prevnode[e.to] = from;
                    prevedge[e.to] = k;
                    prevflow[e.to] = min(prevflow[from], e.cap - e.flow);
                }
            }
        }

        q.pop();
    }
}

void mincutflow(int& flowMax, int& costMin) {
    bellmanFord();
    dijkstra();
    while(distdij[dest] < INT_MAX) {
        int deltaFlow = prevflow[dest];
        flowMax += deltaFlow;

        for(int i = dest; i != src; i = prevnode[i]) {
            Muchie& e = g[prevnode[i]][prevedge[i]];

            costMin += deltaFlow * e.cost;
            e.flow += deltaFlow;
            g[e.to][e.rev].flow -= deltaFlow;
        }

        for(int i = 0; i <= dest; ++ i) {
            dist[i] += distdij[i];
        }
        dijkstra();
    }
}

int main() {
    freopen("cmcm.in", "r", stdin);
    freopen("cmcm.out", "w", stdout);

    int muchii;
    scanf("%d%d%d", &n, &m, &muchii);
    src = 0;
    dest = n + m + 1;

    for(int i = 1; i <= muchii; ++ i) {
        int x, y, cost;
        scanf("%d%d%d", &x, &y, &cost);
        y += n;

        g[x].push_back({y, g[y].size(), 0, 1, cost, i});
        g[y].push_back({x, g[x].size() - 1, 0, 0, -cost});
    }

    for(int i = 1; i <= n; ++ i) {
        g[src].push_back({i, g[i].size(), 0, 1, 0});
        g[i].push_back({src, g[src].size() - 1, 0, 0, 0});
    }

    for(int i = 1; i <= m; ++ i) {
        g[i + n].push_back({dest, g[dest].size(), 0, 1, 0});
        g[dest].push_back({i + n, g[i].size() - 1, 0, 0, 0});
    }

    int flowMax = 0, costMin = 0;
    mincutflow(flowMax, costMin);

    printf("%d %d\n", flowMax, costMin);

    for(int i = 1; i <= n; ++ i) {
        for(int k = 0; k < g[i].size(); ++ k) {
            Muchie& e = g[i][k];

            if(e.flow == e.cap && e.to != src && e.to != dest) {
                printf("%d ", e.ind);
            }
        }
    }

    return 0;
}