Cod sursa(job #3160469)

Utilizator PHOSSESSEDProsie Radu-Teodor PHOSSESSED Data 24 octombrie 2023 10:39:53
Problema Flux maxim de cost minim Scor 10
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.43 kb
#include<fstream>
#include<vector>
#include<queue>
using namespace std;
using pii = pair<int,int>;

ifstream cin("fmcm.in");
ofstream cout("fmcm.out");

class MCMF
{
    private :
    struct muchie
    {
        int cap,flow,cost;
        muchie(int a,int c) : cap(a),flow(0),cost(c) {};
        int rez(){return (cap - flow);}
    };

    const int oo = 1 << 29;

    vector<muchie> e; vector<int> dist,pi; int s,t;
    vector<vector<pii>> vecini; vector<pii> ta;

    void bf()
    {
        queue<int> q; vector<bool> inq(t + 1);
        fill(pi.begin(),pi.end(),oo); pi[s] = 0;
        q.push(s); while(q.empty())
        {
            int v = q.front(); q.pop();
            for(auto &p : vecini[v])
                {
                    int c = e[p.second].cost;
                    if(pi[p.first] > pi[v] + c)
                        {
                            pi[p.first] = pi[v] + c;
                            if(!inq[p.first])
                                {
                                    inq[p.first] = 1;
                                    q.push(p.first);
                                }
                        }
                }
        }
    }

    bool dijkstra()
    {
        priority_queue<pii,vector<pii>,greater<pii>> pq;
        fill(dist.begin(),dist.end(),oo); dist[s] = 0; pq.push({0,s});
        for(int i = 0; i < dist.size() ; i++) ta[i] = {-1,-1};

        while(!pq.empty())
            {
                pii info = pq.top(); pq.pop();
                if(dist[info.second] != info.first) continue;
                int v = info.second; //cout << v << endl;
                for(auto &p : vecini[v])
                    {
                        int rem = e[p.second].rez();
                        if(rem)
                            {
                                int fake = e[p.second].cost + pi[p.first] - pi[v];
                                if(fake < dist[p.first])
                                    {
                                        dist[p.first] = dist[v] + e[p.second].cost;
                                        pq.push({dist[p.first],p.first});
                                        ta[p.first] = {v,p.second};
                                    }
                            }
                    }
            }

        pi.swap(dist);
        return pi[t] != oo;
    }

    public :

    MCMF(int so,int sink,int n) : s(so),t(sink) {vecini.resize(n + 1),dist.resize(n + 1),pi.resize(n + 1),ta.resize(n + 1);}
    void add(int a,int b,int c,int d)
    {
        int now = e.size();
        e.push_back(muchie(c,d)); vecini[a].push_back({b,now});
        e.push_back(muchie(0,-d)); vecini[b].push_back({a,now^1});
    }

    pair<int,int> go()
    {
        pair<int,int> ans = {0,0};
        bf(); while(dijkstra())
        {
            int delta(oo); //cout << delta << endl;
            for(int i = t; i != s; i = ta[i].first) delta = min(delta,e[ta[i].second].rez());
            for(int i = t; i != s; i = ta[i].first) e[ta[i].second].flow += delta,e[ta[i].second^1].flow -= delta;

            ans.first += delta;
            ans.second += delta * pi[t];
        }

        return ans;
    }
};

int main()
{
    int n,m,s,d,a,b,ca,co; cin >> n >> m >> s >> d;
    MCMF g(s,d,n); for(int i = 0 ; i < m ; i++)
    {
        cin >> a >> b >> ca >> co;
        g.add(a,b,ca,co);
    }

    cout << g.go().second;

}