Cod sursa(job #3261050)

Utilizator matei0000Neacsu Matei matei0000 Data 4 decembrie 2024 10:53:04
Problema Cuplaj maxim de cost minim Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.21 kb
#include <bits/stdc++.h>

using namespace std;

const int INF = 1e9;

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

int sus;

struct Dinic
{
    int n;
    struct edge
    {
        int from, to, cost, cap;
    };
    vector<edge> muchii;
    vector<vector<int>> edges;
    vector<bool> viz;
    vector<int> prv, dist;
    Dinic(int N)
    {
        n = N;
        edges.resize(n);
        viz.resize(n);
        dist.resize(n);
        prv.resize(n);
    }
    void addEdge(int from, int to, int cost, int cap)
    {
        edges[from].push_back(muchii.size());
        muchii.push_back({from, to, cost, cap});
        edges[to].push_back(muchii.size());
        muchii.push_back({to, from, -cost, 0});
    }
    bool bellman(int source, int dest)
    {
        for(int i = 0; i < n; i ++)
            dist[i] = INF;
        vector<bool> inQ(n);
        queue<int> q;
        q.push(source);
        dist[source] = 0;
        while(!q.empty())
        {
            int node = q.front();
            inQ[node] = false;
            q.pop();
            for(auto i : edges[node])
            {
                edge e = muchii[i];
                if(e.cap && dist[node] + e.cost < dist[e.to])
                {
                    dist[e.to] = dist[node] + e.cost;
                    if(!inQ[e.to])
                    {
                        q.push(e.to);
                        inQ[e.to] = true;
                    }
                }
            }
        }
        return dist[dest] != INF;
    }
    bool dijkstra(int source, int dest)
    {
        vector<bool> viz(n, 0);
        vector<int> fakeDist(n, INF);
        vector<int> realDist(n);
        for(int i = 0; i < n; i ++)
        {
            realDist[i] = dist[i];
            prv[i] = -1;
        }
        priority_queue<pair<int, int>> pq;
        pq.push({0, source});
        dist[source] = fakeDist[source] = 0;
        while(!pq.empty())
        {
            int node = pq.top().second;
            pq.pop();
            if(!viz[node])
            {
                viz[node] = true;
                for(auto i : edges[node])
                {
                    edge e = muchii[i];
                    if(e.cap && fakeDist[node] + realDist[node] + e.cost - realDist[e.to] < fakeDist[e.to])
                    {
                        fakeDist[e.to] = fakeDist[node] + realDist[node] + e.cost - realDist[e.to];
                        dist[e.to] = dist[node] + e.cost;
                        prv[e.to] = i;
                        pq.push({-fakeDist[e.to], e.to});
                    }
                }
            }
        }
        return fakeDist[dest] != INF;
    }
    pair<int, int> push(int source, int dest)
    {
        int flow = INF, c = 0;
        for(int node = dest; node != source; node = muchii[prv[node]].from)
        {
            flow = min(flow, muchii[prv[node]].cap);
            c += muchii[prv[node]].cost;
        }
        for(int node = dest; node != source; node = muchii[prv[node]].from)
        {
            muchii[prv[node]].cap -= flow;
            muchii[prv[node] ^ 1].cap += flow;
        }
        return {flow, flow * c};
    }
    pair<int, int> maxFlowMinCost(int source, int dest)
    {
        int maxFlow = 0, minCost = 0;
        if(!bellman(source, dest))
            return {0, 0};
        while(dijkstra(source, dest))
        {
            auto p = push(source, dest);
            maxFlow += p.first;
            minCost += p.second;
        }
        out << maxFlow << " " << minCost << '\n';
        for(int i = 0; i < muchii.size(); i += 2)
            if(muchii[i].cap == 0 && muchii[i].from < sus)
                out << i / 2 + 1 << " ";
        return {maxFlow, minCost};
    }
};

int main()
{
    int n, m, k;
    in >> n >> m >> k;
    sus = n;
    Dinic ds(n + m + 2);
    for(int i = 0; i < k; i ++)
    {
        int f, t, c;
        in >> f >> t >> c;
        f --, t --;
        ds.addEdge(f, t + n, c, 1);
    }
    for(int i = 0; i < n; i ++)
        ds.addEdge(n + m, i, 0, 1);
    for(int i = n; i < n + m; i ++)
        ds.addEdge(i, n + m + 1, 0, 1);
    ds.maxFlowMinCost(n + m, n + m + 1);
}