Cod sursa(job #2112120)

Utilizator Mihai_PredaPreda Mihai Dragos Mihai_Preda Data 23 ianuarie 2018 00:37:33
Problema Cuplaj maxim de cost minim Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.39 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <queue>

using namespace std;

const int INF = (1 << 29);

class flow
{
public:
    vector<vector<int> > cap;
    vector<vector<int> > flux;
    flow(int n)
    {
        this->n = n;
        vecini.resize(n + 1);
        cap.resize(n + 1, vector<int>(n + 1));
        cost.resize(n + 1, vector<int>(n + 1));
        dp.resize(n+1);
        viz.resize(n+1);
        flux.resize(n+1, vector<int>(n+1));
    }
    void AddEdge(int x, int y, int capacity, int cost)
    {
        vecini[x].push_back(y);
        vecini[y].push_back(x);
        cap[x][y] = capacity;
        this->cost[x][y] = cost;
        this->cost[y][x] = -cost;
    }
    long long GetMinCostMaxFlow(int source, int dest)
    {
        long long ret = 0;
        vector<int> father(n+1);
        while(BellmanFord(source, dest, flux, father))
        {
            int mn = INF;
            for(int nod = dest; nod != source; nod = father[nod])
                mn = min(mn, cap[father[nod]][nod] - flux[father[nod]][nod]);
            for(int nod = dest; nod != source; nod = father[nod])
            {
                ret += 1LL * cost[father[nod]][nod] * mn;
                flux[father[nod]][nod] += mn;
                flux[nod][father[nod]] -= mn;
            }
        }
        return ret;
    }
private:
    bool BellmanFord(int source, int dest, vector<vector<int> > &flux, vector<int> &father)
    {
        bool ret = false;
        fill(dp.begin(), dp.end(), INF);
        queue<int> q;
        q.push(source);
        dp[source] = 0;
        viz[source] = true;
        int nod;
        while(q.empty() == false)
        {
            nod = q.front();
            q.pop();
            if(nod == dest)
                ret = true;
            viz[nod] = false;
            for(auto v:vecini[nod])
            {
                if(cap[nod][v] == flux[nod][v])
                    continue;
                if(dp[nod] + cost[nod][v] < dp[v])
                {
                    dp[v] = dp[nod] + cost[nod][v];
                    father[v] = nod;
                    if(viz[v] == false)
                    {
                        q.push(v);
                        viz[v] = true;
                    }
                }
            }
        }
        return ret;
    }
    int n;
    vector<vector<int> > vecini;
    vector<vector<int> > cost;
    vector<int> dp;
    vector<bool> viz;

};

int main()
{
    ifstream in("cmcm.in");
    int n, m, e, p, q, c;
    in >> n >> m >> e;
    vector<vector<int> > edgeId(n+1, vector<int>(m+1));
    int source = n + m + 1, dest = n + m + 2;
    flow gr(n + m + 2);
    for(int i = 1; i <= e; ++i)
    {
        in >> p >> q >> c;
        gr.AddEdge(p, n + q, 1, c);
        edgeId[p][q] = i;
    }
    in.close();
    for(int i = 1; i <= n; ++i)
        gr.AddEdge(source, i, 1, 0);
    for(int i = 1; i <= m; ++i)
        gr.AddEdge(n + i, dest, 1, 0);

    ofstream out("cmcm.out");
    int cost = gr.GetMinCostMaxFlow(source, dest);
    vector<int> rasp;
    for(int i = 1; i <= n; ++i)
        for(int j = n + 1; j <= n + m; ++j)
            if(gr.flux[i][j] && gr.cap[i][j])
                rasp.push_back(edgeId[i][j-n]);
    out << rasp.size() << " " << cost << "\n";
    for(auto x:rasp)
        out << x << " ";
    out.close();
    return 0;
}