Cod sursa(job #2695429)

Utilizator vladboss2323Ciorica Vlad vladboss2323 Data 12 ianuarie 2021 22:44:04
Problema Cuplaj maxim de cost minim Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.26 kb
#include <bits/stdc++.h>

using namespace std;


ifstream in("cmcm.in");
ofstream out("cmcm.out");

struct Graph
{
    int l, r, n, s, d;
    vector < vector <int> > a;
    vector < vector <int> > cap, cost;
    vector <int> dcost, flow, parent;
    queue <int> Q;
    priority_queue < pair <int, int> > Heap;
    vector <bool> viz;

    Graph(int _l, int _r): l(_l), r(_r), n(r + l + 2), s(0), d(n - 1), a(n),
        cap(n, vector<int>(n)), cost(cap), dcost(n),
        flow(n), parent(n), viz(n)
    {
        for (int i = 1; i <= l; ++i)
            AddEdge(0, i, 1, 0);

        for (int i = l + 1; i <= l + r; ++i)
            AddEdge(i, d, 1, 0);
    }

    void AddEdge(int x, int y, int cp, int cst)
    {
        a[x].push_back(y);
        a[y].push_back(x);
        cap[x][y] += cp;
        cost[x][y] += cst;
        cost[y][x] -= cst;
    }

    void Bellman()
    {
        fill(dcost.begin(), dcost.end(), 1e9);
        fill(viz.begin(), viz.end(), 0);

        Q.push(s);
        dcost[s] = 0;
        viz[s] = 1;

        while (not Q.empty())
        {
            int node = Q.front();
            Q.pop();
            viz[node] = 0;

            int curr_cost = dcost[node];

            for (int nei: a[node])
            {
                if (!cap[node][nei])
                    continue;

                int new_dist = curr_cost + cost[node][nei];
                if (new_dist < dcost[nei])
                {
                    dcost[nei] = new_dist;
                    if (!viz[nei])
                    {
                        viz[nei] = 1;
                        Q.push(nei);
                    }
                }
            }
        }
    }

    pair <int, int> Dijkstra()
    {
        fill(flow.begin(), flow.end(), 1e9);
        vector <int> aux(n, 1e9);

        Heap.push({0, s});
        flow[s] = 0;
        aux[s] = 0;

        while (!Heap.empty())
        {
            int curr_cost = -Heap.top().first;
            int node = Heap.top().second;
            Heap.pop();

            if (curr_cost != flow[node])
                continue;

            for (int nei: a[node])
            {
                if (!cap[node][nei])
                    continue;
                int new_dist = curr_cost + cost[node][nei] + dcost[node] - dcost[nei];
                if (new_dist < flow[nei])
                {
                    flow[nei] = new_dist;
                    Heap.push({-flow[nei], nei});
                    parent[nei] = node;
                    aux[nei] = aux[node] + cost[node][nei];
                }
            }
        }

        if (flow[d] == 1e9)
            return {0, 0};

        int flow = 1e9;
        for (int node = d; node != s; node = parent[node])
            flow = min(flow, cap[parent[node]][node]);

        for (int node = d; node != s; node = parent[node])
        {
            cap[parent[node]][node] -= flow;
            cap[node][parent[node]] += flow;
        }

        dcost = aux;

        return {flow, dcost[d] * flow};
    }

    pair <int, int> MinCostMaxFlow()
    {
        Bellman();

        int maxFlow = 0, minCost = 0;
        while(1)
        {
            auto lol = Dijkstra();
            if (lol.first == 0)
                break;

            maxFlow += lol.first;
            minCost += lol.second;
        }

        return {maxFlow, minCost};
    }

    vector <int> getUsedEdges(vector <pair <int, int> >& edges)
    {
        vector <int> ans;

        for (int i = 0; i < (int) edges.size(); ++i)
        {
            int a = edges[i].first;
            int b = edges[i].second;
            if (!cap[a][b])
                ans.push_back(i + 1);
        }

        return ans;
    }
};



int main()
{

    int l, r, m;
    in >> l >> r >> m;

    Graph G(l, r);

    vector < pair <int, int> > edges;
    for (int i = 1; i <= m; ++i)
    {
        int a, b, z;
        in >> a >> b >> z;
        G.AddEdge(a, l + b, 1, z);
        edges.push_back({a, l + b});
    }

    auto ans = G.MinCostMaxFlow();
    out << ans.first << ' ' << ans.second << '\n';

    auto vec = G.getUsedEdges(edges);
    for (int it : vec)
        out << it << ' ';

    return 0;
}