Cod sursa(job #2691108)

Utilizator felixiPuscasu Felix felixi Data 27 decembrie 2020 10:59:25
Problema Cuplaj maxim de cost minim Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 5.05 kb
#pragma region GCC_CP_Directives
#ifndef ITS_PERSONAL
    #define __FAST_GCC_DIRECTIVE_1 GCC optimize("Ofast")
    #define __FAST_GCC_DIRECTIVE_2 GCC optimize ("unroll-loops")
    #define __FAST_GCC_DIRECTIVE_3 GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")

    #pragma OPTIMIZE1
    #pragma OPTIMIZE2
    #pragma OPTIMIZE3

    #undef __FAST_GCC_DIRECTIVE_1
    #undef __FAST_GCC_DIRECTIVE_2
    #undef __FAST_GCC_DIRECTIVE_3
#endif
#pragma endregion GCC_CP_Directives

#pragma comment(linker, "/STACK:256000000")

#include <bits/stdc++.h>

using namespace std;

/// MACROs
#define FOR(i,a,b) for(int i = (a); i <= (b); ++i)

// Meta constants
#define USE_FILES 1

#if USE_FILES == 1
    ifstream fffin("cmcm.in");
    ofstream fffout("cmcm.out");
#endif

// Meta constants
const bool MULTIPLE_CASES = 0;
const bool PRINT_CASE_MSG = 0;

const int DOUBLE_PRECISION = 6;  // 0 - don't set fixed precision, 

struct Flux_minCost
{
    // CAREFUL!!
    // does NOT support multi-edges between 2 nodes

    static constexpr int NODES = 300 * 2 + 5;
    static constexpr int INF   = 1e9;

    int n;
    int cap[NODES + 2][NODES + 2];
    int cost[NODES + 2][NODES + 2];

    Flux_minCost(int nodes) : n(nodes)
    { }

    void setEdge(int from, int to, int capacity, int price)
    {
        cap[from][to] += capacity;
        cost[from][to] = price;
        cost[to][from] = -price;
    }

    pair<int, int> maxflow_mincost(int source, int dest)
    {
        assert(1 <= source && source <= n);
        assert(1 <= dest && dest <= n);

        int father[NODES + 2];
        fill(father, father + NODES + 2, 0);

        auto bellman = [&]() -> bool 
        {
            int dist[NODES + 2];
            queue<int> q;
            bool in_queue[NODES + 2];

            fill(dist, dist + NODES + 1, INF);
            dist[source] = 0;
            q.push(source);
            in_queue[source] = true;

            while (!q.empty()) {
                int nod = q.front();
                in_queue[nod] = false;
                q.pop();

                for (int i = 1; i <= NODES; ++i) {
                    if (cap[nod][i] && dist[nod] + cost[nod][i] < dist[i]) {
                        dist[i] = dist[nod] + cost[nod][i];
                        father[i] = nod;
                        if (!in_queue[i]) {
                            in_queue[i] = true;
                            q.push(i);
                        }
                    }
                }
            }
            return dist[dest] != INF;
        };

        int flowed = 0, ans = 0;

        while (bellman()) {
            int minim = INF;

            int nod = dest;
            while (father[nod]) {
                minim = min(minim, cap[father[nod]][nod]);
                nod = father[nod];
            }
            flowed += minim;

            nod = dest;
            while (father[nod]) {
                cap[ father[nod] ][ nod ] -= minim;
                cap[ nod ][ father[nod] ] += minim;

                ans += minim * cost[ father[nod] ][ nod ];
                nod = father[nod];
            }
        }

        return {flowed, ans};
    }
};

// type definitions
using i64 = long long;
using pii = pair<int, int>;
using Graph = vector<vector<int>>;

// Problem constants
const int INF  = (1 << 30);
const int NMAX = 8e4 + 3;

void solve()
{
    int N, M, E;
    cin >> N >> M >> E;
    vector<pii> edges;
    Flux_minCost flux(N + M + 2);
    FOR (i, 1, E) {
        int x, y, c;
        cin >> x >> y >> c;
        edges.push_back({x, N + y});
        flux.setEdge(x, N + y, 1, c);
    }
    FOR (i, 1, N)
        flux.setEdge(N + M + 1, i, 1, 0);
    FOR (i, N + 1, N + M) 
        flux.setEdge(i, N + M + 2, 1, 0);
    
    auto leFlow = flux.maxflow_mincost(N + M + 1, N + M + 2);
    cout << leFlow.first << ' ' << leFlow.second << '\n';
    
    FOR (i, 1, E) {
        int x = edges[i - 1].first, y = edges[i - 1].second;
        if (flux.cap[x][y] == 0)
            cout << i << ' ';
    }
    cout << '\n';
}

int main()
{
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

    #if USE_FILES == 1
        cin.rdbuf(fffin.rdbuf());
        cout.rdbuf(fffout.rdbuf());
    #endif

    #ifdef ITS_PERSONAL
        auto _time_begin = std::chrono::high_resolution_clock::now();
    #endif

    if (DOUBLE_PRECISION > 0)
        cout << setprecision(DOUBLE_PRECISION) << fixed;

    auto testMessage = [](int id) {
        return "Case #" + to_string(id) + ": ";
    };

    int T = 1;
    if (MULTIPLE_CASES)
        cin >> T;

    for (int t = 1; t <= T; ++t) {
        cout << (PRINT_CASE_MSG ? testMessage(t) : "");
        solve();
    }

    #ifdef ITS_PERSONAL
        auto _time_end = std::chrono::high_resolution_clock::now();
		cerr << setprecision(4) << fixed;
		cerr << "Execution time: " << std::chrono::duration_cast<std::chrono::duration<double>>(_time_end - _time_begin).count() << " seconds" << endl;
    #endif
}