Cod sursa(job #2965063)

Utilizator andu2006Alexandru Gheorghies andu2006 Data 14 ianuarie 2023 13:06:07
Problema Flux maxim de cost minim Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.95 kb
#include <bits/stdc++.h>
//#pragma GCC optimize("unroll-loops")

using namespace std;
typedef long long ll;
typedef pair<ll,ll> pll;
const int NMAX=355,MMAX=12505,INF=1e9;
struct edge{
    int u, v, cap, flow, cost;
}edges[MMAX*2];
int id[NMAX][NMAX];
vector<ll> edg[NMAX];
int bellman_dist[NMAX],dist[NMAX],start,sink;
int prv[NMAX];
random_device rd;
mt19937 gen(rd());
int rndnext(int l, int r){
    uniform_int_distribution<int> rnd(l,r);
    return rnd(gen);
}
int main()
{
    ifstream fin("fmcm.in");
    ofstream fout("fmcm.out");
    int n,m;
    fin>>n>>m>>start>>sink;
    for(int i=0;i<m;i++){
        fin>>edges[i*2].u>>edges[i*2].v>>edges[i*2].cap>>edges[i*2].cost;
        edges[i*2+1]={edges[i*2].v,edges[i*2].u,0,0,-edges[i*2].cost};
        id[edges[i*2].u][edges[i*2].v]=i*2;
        id[edges[i*2+1].u][edges[i*2+1].v]=i*2+1;
        edg[edges[i*2].u].push_back(i*2);
        edg[edges[i*2+1].u].push_back(i*2+1);
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<edg[i].size();j++){
            int k=rndnext(0,j);
            if(k!=j) swap(edg[i][k],edg[i][j]);
        }
    }
    if(start==sink){
        fout<<0;
        return 0;
    }
    for(int i=1;i<=n;i++) bellman_dist[i]=1e9;
    bellman_dist[start]=0;
    for(int iter=0;iter<n;iter++){
        for(int it=0;it<2*m;it+=2)
            bellman_dist[edges[it].v]=min(bellman_dist[edges[it].v],bellman_dist[edges[it].u]+edges[it].cost);
    }
    for(int it=0;it<2*m;it++){
        //if(it%2==0)
            edges[it].cost+=bellman_dist[edges[it].u]-bellman_dist[edges[it].v];
        //else
        //    edges[it].cost+=bellman_dist[edges[it].v]-bellman_dist[edges[it].u];
    }
    int ans=0,cost=0;
    while(1){
        set<pair<int,int>> s;
        for(int i=1;i<=n;i++) dist[i]=INF,prv[i]=-1;
        dist[start]=0,prv[start]=start;
        s.insert({dist[start],start});
        while(!s.empty()){
            int u=s.begin()->second;
            s.erase(s.begin());
            if(u==sink){
                s.clear();
                break;
            }
            for(const auto &it : edg[u]){
                if(edges[it].flow<edges[it].cap && dist[u]+edges[it].cost<dist[edges[it].v]){
                    if(dist[edges[it].v]!=INF) s.erase({dist[edges[it].v],edges[it].v});
                    dist[edges[it].v]=dist[u]+edges[it].cost;
                    s.insert({dist[edges[it].v],edges[it].v});
                    prv[edges[it].v]=u;
                }
            }
        }
        if(prv[sink]==-1) break;
        int total_flow=INF,aux=sink;
        while(aux!=start){
            int it=id[prv[aux]][aux];
            total_flow=min(total_flow,edges[it].cap-edges[it].flow);
            aux=prv[aux];
        }
        aux=sink;
        ans+=total_flow,cost+=(dist[sink]+bellman_dist[sink])*total_flow;
        while(aux!=start){
            int it=id[prv[aux]][aux];
            edges[it].flow+=total_flow,edges[it^1].flow-=total_flow;
            aux=prv[aux];
        }
    }
    fout<<cost;
    return 0;
}