Cod sursa(job #3120924)

Utilizator HandoMihnea-Vicentiu Hando Data 9 aprilie 2023 13:44:58
Problema Cuplaj maxim de cost minim Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 6.29 kb
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

#define ar array
#define vt vector
#define pq priority_queue
#define pu push
#define pub push_back
#define em emplace
#define emb emplace_back
#define mt make_tuple

#define all(x) x.begin(), x.end()
#define allr(x) x.rbegin(), x.rend()
#define allp(x, l, r) x.begin() + l, x.begin() + r
#define len(x) (int)x.size()
#define uniq(x) unique(all(x)), x.end()

using namespace std;
using namespace __gnu_pbds;

using ll = long long;
using ld = long double;
using ull = unsigned long long;

template <class T, size_t N>
void re(array <T, N>& x);
template <class T> 
void re(vt <T>& x);

template <class T> 
void re(T& x) {
    cin >> x;
}

template <class T, class... M> 
void re(T& x, M&... args) {
    re(x); re(args...);
}

template <class T> 
void re(vt <T>& x) {
    for(auto& it : x)
        re(it);
}

template <class T, size_t N>
void re(array <T, N>& x) {
    for(auto& it : x)
        re(it);
}

template <class T, size_t N>
void wr(array <T, N> x);
template <class T> 
void wr(vt <T> x);

template <class T> 
void wr(T x) {
    cout << x;
}

template <class T, class ...M>  void wr(T x, M... args) {
    wr(x), wr(args...);
}

template <class T> 
void wr(vt <T> x) {
    for(auto it : x)
        wr(it, ' ');
}

template <class T, size_t N>
void wr(array <T, N> x) {
    for(auto it : x)
        wr(it, ' ');
}

template<class T, class... M>
auto mvt(size_t n, M&&... args) {
    if constexpr(sizeof...(args) == 1)
        return vector<T>(n, args...);
    else
        return vector(n, mvt<T>(args...));
}

void set_fixed(int p = 0) {
    cout << fixed << setprecision(p);
}

void set_scientific() {
    cout << scientific;
}

inline void Open(const string Name) {
    #ifndef ONLINE_JUDGE
        (void)!freopen((Name + ".in").c_str(), "r", stdin);
        (void)!freopen((Name + ".out").c_str(), "w", stdout);
    #endif
}

const int INF = 1e9;

struct MCMF {
    struct edge {
        int u, v;
        int cap, cost;
        int id;
 
        edge(int _u, int _v, int _cap, int _cost, int _id) {
            u = _u;
            v = _v;
            cap = _cap;
            cost = _cost;
            id = _id;
        }
    };
 
    int n, s, t, mxid;
    int flow, cost;
    vt <vt <int>> g;
    vt <edge> e;
    vt <int> d, inQ, potential, flow_through;
    vt <int> par;
    bool neg;
    MCMF() {
 
    }
    MCMF(int _n) {
        n = _n + 10;
        g.assign(n, vt<int>());
        neg = false;
        mxid = 0;
    }
 
    void add_edge(int u, int v, int cap, int cost, int id = -1, bool directed = true) {
        if(cost < 0) {
            neg = true;
        }
        g[u].pub(len(e));
        e.pub({u, v, cap, cost, id});
        g[v].pub(len(e));
        e.pub({v, u, 0, -cost, -1});
        mxid = max(mxid, id);
        if(!directed) {
            add_edge(v, u, cap, cost, -1, true);
        }
    }
    bool dijkstra() {
        par.assign(n, -1);
        d.assign(n, INF);
        priority_queue <pair <int, int>, vt <pair <int, int>>, greater <pair <int, int>>> q;
        d[s] = 0;
        q.em(0, s);
        while(!q.empty()) {
            int u = q.top().second;
            int nw = q.top().first;
            q.pop();
            if(nw != d[u]) 
                continue;
            for(int i = 0;i < len(g[u]);i++) {
                int id = g[u][i];
                int v = e[id].v;
                int cap = e[id].cap;
                int w = e[id].cost + potential[u] - potential[v];
                
                if(d[u] + w < d[v] && cap > 0) {
                    d[v] = d[u] + w;
                    par[v] = id;
                    q.em(d[v], v);
                }
            }
        }
        for(int i = 0;i < n;i++) {
            if(d[i] < INF) 
                potential[i] += d[i];
        }
        return d[t] != INF;
    }
 
    int send_flow(int v, int cur) {
        if(par[v] == -1) {
            return cur;
        }
        int id = par[v];
        int u = e[id].u;
        int w = e[id].cost;
        int f = send_flow(u, min(cur, e[id].cap));
        cost += f * w;
        e[id].cap -= f;
        e[id ^ 1].cap += f;
        return f;
    }
 
    //returns {maxflow, mincost}
    pair <int, int> solve(int _s, int _t, int goal = INF) {
        s = _s;
        t = _t;
        flow = 0, cost = 0;
        potential.assign(n, 0);
        if(neg) {
            // run Bellman-Ford to find starting potential
            d.assign(n, INF);
            inQ.assign(n, 0);
            queue <int> q;
            q.em(s), d[s] = 0;
            while(!q.empty()) {
                int u = q.front();
                q.pop();
                inQ[u] = 0;
                for (int k = 0; k < len(g[u]); k++) {
                    int id = g[u][k];
                    int v = e[id].v;
                    int cap = e[id].cap, w = e[id].cost;
                    if(d[v] > d[u] + w && cap > 0) {
                        d[v] = d[u] + w;
                        if(!inQ[v]) {
                            q.em(v);
                            inQ[v] = 1;
                        }
                    }
                }
            }
            for(int i = 0;i < n;i++) {
                if(d[i] < INF) {
                    potential[i] = d[i];
                }
            }
        }
        while(flow < goal && dijkstra()) {
            flow += send_flow(t, goal -flow);
        }
        flow_through.assign(mxid + 10, 0);
        for(int u = 0; u < n; u++) {
            for(auto v : g[u]) {
                if(e[v].id >= 0) 
                    flow_through[e[v].id] = e[v ^ 1].cap;
            }
        }
        return make_pair(flow, cost);
    }
};

void solve() {
    int n, m, e; re(n, m, e);
    MCMF G(n + m + 5);
    for (int i = 0; i < e; ++i) {
        int u, v, c; re(u, v, c);
        --u, --v;
        G.add_edge(u, v + n, 1, c, i);
    }

    int s = n + m, t = s + 1;
    for (int i = 0; i < n; ++i) {
        G.add_edge(s, i, 1, 0);
    }

    for (int i = 0; i < m; ++i) {
        G.add_edge(i + n, t, 1, 0);
    }

    auto [cup, cost] = G.solve(s, t);
    wr(cup, ' ', cost, '\n');
    for(int u = 0; u < e; u++)
        if(G.flow_through[u]) {
            wr(u + 1, ' ');
        }

}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);

    Open("cmcm");

    int t = 1;
    for(;t;t--) {
        solve();
    }
    
    return 0;
}