Cod sursa(job #2925952)

Utilizator UnknownPercentageBuca Mihnea-Vicentiu UnknownPercentage Data 16 octombrie 2022 14:23:16
Problema Cuplaj maxim de cost minim Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 5.61 kb
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
 
#define vt vector
#define pb push_back
#define em emplace
#define emb emplace_back
 
#define all(x) x.begin(), x.end()
#define all1(x) x.begin() + 1, x.end()
#define sz(x) (int)(x).size()
 
using namespace std;
using namespace __gnu_pbds;
 
using ll = long long;
using ld = long double;
using ull = unsigned long long;
 
template <class T> void re(vt <T>& x);
template <class T> void re(T& x) {
    cin >> x;
}
 
template <class H, class... T> void re(H &x, T&... y) {
    re(x); re(y...);
}
 
template <class T> void re(vt <T>& x) {
    for(auto& it : x)
        re(it);
}
 
template <class T> void wr(T x) {
    cout << x;
}
 
template <class H, class ...T> void wr(H x, T... y) {
    wr(x); wr(y...);
}
 
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, 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].pb(sz(e));
        e.pb(edge(u, v, cap, cost, id));
        g[v].pb(sz(e));
        e.push_back(edge(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 < sz(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);
            queue <int> q;
            vt <bool> inQ(n, 0);
            q.em(s), d[s] = 0;
            while(!q.empty()) {
                int u = q.front();
                q.pop();
                inQ[u] = 0;
                for (int k = 0; k < sz(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 F(n + m);
    for(int i = 0;i < e;i++) {
        int a, b, c; re(a, b, c);
        --a, --b;
        F.add_edge(a, b + n, 1, c, i);
    }
 
    int s = n + m, t = s + 1;
    for(int i = 0;i < n;i++) {
        F.add_edge(s, i, 1, 0);
    }
    for(int i = 0;i < m;i++) {
        F.add_edge(i + n, t, 1, 0);
    }
 
    auto res = F.solve(s, t);
    wr(res.first, ' ', res.second, '\n');
    for(int u = 0;u < e;u++)
        if(F.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;
}