Cod sursa(job #1578021)

Utilizator retrogradLucian Bicsi retrograd Data 24 ianuarie 2016 04:34:45
Problema Cuplaj maxim de cost minim Scor 50
Compilator cpp Status done
Runda Arhiva educationala Marime 4.43 kb
#include <iostream>
#include <queue>
#include <cstring>
#include <cstdio>

using namespace std;

struct Flow {
    const static int MAX_EDGES = 100005;
    const static int MAX_NODES = 1000;
    const int INF = 1e9 + 50;

    int S = MAX_NODES - 2, D = MAX_NODES - 1;

    int G[MAX_NODES];
    struct Edge {
        int vec, flow, cap, cost, rev, nxt;
    };
    Edge E[MAX_EDGES];
    int edges = 0;

    int ParentNode[MAX_NODES], ParentEdge[MAX_NODES], Dist[MAX_NODES], DistOld[MAX_NODES], DistReal[MAX_NODES];
    bool InQ[MAX_NODES];
    queue<int> Q;
    priority_queue<pair<int, int>> PQ;

    Flow() {
        Reset();
    }

    void setSource(int s) {
        S = s;
    }
    void setSink(int d) {
        D = d;
    }

    void _addEdge(int a, int b, int cap, int cost, int rev) {
        ++edges;
        E[edges] = (Edge) {b, 0, cap, cost, rev, G[a]};
        G[a] = edges;
    }
    void AddEdge(int a, int b, int cap, int cost) {
        _addEdge(a, b, cap, cost, edges + 2);
        _addEdge(b, a, 0, -cost, edges);
    }

    bool Bellman() {
        memset(ParentNode, 0, sizeof(ParentNode));

        DistOld[S] = 0;
        Q.push(S);


        while(!Q.empty()) {
            int top = Q.front();
            InQ[top] = 0;
            Q.pop();

            for(int i=G[top]; i; i=E[i].nxt) {
                int vec = E[i].vec;
                if(E[i].flow < E[i].cap && (ParentNode[vec] == 0 || DistOld[vec] > DistOld[top] + E[i].cost)) {
                    DistOld[vec] = DistOld[top] + E[i].cost;
                    ParentNode[vec] = top;
                    ParentEdge[vec] = i;

                    if(!InQ[vec]) {
                        Q.push(vec);
                        InQ[vec] = 1;
                    }
                }
            }
        }

        return ParentNode[D] != 0;
    }

    bool Dijkstra() {
        memset(ParentNode, 0, sizeof(ParentNode));

        Dist[S] = DistReal[S] = 0;
        PQ.push({0, S});

        while(!PQ.empty()) {
            auto top = PQ.top();
            PQ.pop();
            int node = top.second;

            if(-top.first > Dist[node])
                continue;

            for(int i = G[node]; i; i = E[i].nxt) {
                int vec = E[i].vec;

                if(E[i].flow < E[i].cap && (ParentNode[vec] == 0 || Dist[vec] > Dist[node] + DistOld[node] - DistOld[vec] + E[i].cost)) {
                    Dist[vec] = Dist[node] + DistOld[node] - DistOld[vec] + E[i].cost;
                    ParentNode[vec] = node;
                    ParentEdge[vec] = i;
                    DistReal[vec] = DistReal[node] + E[i].cost;
                    PQ.push({-Dist[vec], vec});
                }
            }
        }

        return ParentNode[D] != 0;
    }

    void Reset() {
        edges = 0;
        memset(G, 0, sizeof(G));
        while(!Q.empty()) Q.pop();
        while(!PQ.empty()) PQ.pop();
    }

    pair<int, int> MFMC() {
        int cost = 0, flow = 0;

        Bellman();

        while(Dijkstra()) {
            int M = INF;

            for(int node = D; node != S; node = ParentNode[node]) {
                int ei = ParentEdge[node];
                M = min(M, E[ei].cap - E[ei].flow);
            }

            for(int node = D; node != S; node = ParentNode[node]) {
                int ei = ParentEdge[node],
                    ri = E[ei].rev;

                E[ei].flow += M;
                E[ri].flow -= M;

                cost += E[ei].cost * M;
            }

            flow += M;
            memcpy(DistOld, DistReal, sizeof(DistReal));
        }

        return {flow, cost};
    }

};
Flow F;

int Ind[200000];

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

    int n, m, e;
    cin >> n >> m >> e;

    #define Left(i) 2*i
    #define Right(i) 2*i+1

    for(int i=1; i<=n; i++)
        F.AddEdge(F.S, Left(i), 1, 0);
    for(int i=1; i<=m; i++)
        F.AddEdge(Right(i), F.D, 1, 0);

    int a, b, c;
    for(int i=1; i<=e; i++) {
        cin >> a >> b >> c;

        Ind[F.edges+1] = Ind[F.edges+2] = i;
        F.AddEdge(Left(a), Right(b), 1, c);
    }

    auto ret = F.MFMC();
    cout << ret.first << " " << ret.second << '\n';

    for(int i=1; i<=F.edges; i++) {
        if(F.E[i].flow > 0 && Ind[i] > 0) {
            cout << Ind[i] << " ";
        }
    }

    return 0;
}