Cod sursa(job #1796270)

Utilizator livliviLivia Magureanu livlivi Data 3 noiembrie 2016 11:46:51
Problema Flux maxim de cost minim Scor 20
Compilator cpp Status done
Runda Arhiva educationala Marime 3.34 kb
#include<cstdio>
#include<vector>
#include<queue>
#include<utility>
#include<bitset>
#define N 350
#define MULT 2000000000
using namespace std;

class mazi{
public:
    int nod,cost;

    bool operator < (const mazi a) const{
        return (cost>a.cost);
    }

    bool operator > (const mazi a) const{
        return (cost<a.cost);
    }
};

priority_queue<mazi> heap;

vector<pair<int,int> > vecin[N+1];
vector<int> realC[N+1];
queue<int> Q;
bitset<N+1> mark;
int dist[N+1];
int realD[N+1];
bool in_queue[N+1];
int viz[N+1];
int n;
int S,D;

int c[N+1][N+1];
int f[N+1][N+1];
int R,ans;
int tata[N+1];

bool adauga(int x){
    if (viz[x]==n) return false;
    viz[x]++;

    if (in_queue[x]==false){
        Q.push(x);
        in_queue[x]=true;
    }

    return true;
}

bool bellmanford(int nod){
    adauga(nod);
    dist[nod]=0;

    while(!Q.empty()){
        nod=Q.front();
        Q.pop();
        in_queue[nod]=false;

        for(int i=0;i<vecin[nod].size();i++){
            int now=vecin[nod][i].first;
            int cost=vecin[nod][i].second;

            if (dist[nod]+cost<dist[now] &&c[nod][now]!=0){
                dist[now]=dist[nod]+cost;
                if (!adauga(now)) return false;
            }
        }
    }

    return true;
}

mazi make_mazi(int nod,int cost){
    mazi a;

    a.nod=nod;
    a.cost=cost;

    return a;
}

bool dijkstra(){
    int nod=S;

    mark.reset();
    while(!heap.empty()) heap.pop();
    for(int i=1;i<=n;i++){
        dist[i]=MULT;
        realD[i]=0;
    }

    dist[nod]=0;
    heap.push(make_mazi(nod,dist[nod]));

    while(!heap.empty() &&nod!=D){
        nod=heap.top().nod;
        heap.pop();
        mark.set(nod);

        for(int i=0;i<vecin[nod].size();i++){
            int now=vecin[nod][i].first;
            int cost=vecin[nod][i].second;

            if (dist[now]>dist[nod]+cost &&c[nod][now]-f[nod][now]>0){
                dist[now]=dist[nod]+cost;
                realD[now]=realD[nod]+realC[nod][i];
                tata[now]=nod;
                heap.push(make_mazi(now,dist[now]));
            }
        }

        while(!heap.empty() &&mark[heap.top().nod]==true) heap.pop();
    }

    return mark[D];
}

int minim(int a,int b){
    return (a<b) ? a : b;
}

void flux(){
    int min;

    while(dijkstra()){
        int nod=D;
        min=c[tata[nod]][nod]-f[tata[nod]][nod];
        while(nod!=S){
            min=minim(min,c[tata[nod]][nod]-f[tata[nod]][nod]);
            nod=tata[nod];
        }

        R+=min;
        ans+=(min*realD[D]);
        nod=D;
        while(nod!=S){
            f[tata[nod]][nod]+=min;
            f[nod][tata[nod]]-=min;
            nod=tata[nod];
        }
    }
}

int main(){
    freopen ("fmcm.in","r",stdin);
    freopen ("fmcm.out","w",stdout);
    int m,i,j;

    scanf ("%d%d%d%d",&n,&m,&S,&D);
    for(i=1;i<=m;i++){
        int x,y,z,w;
        scanf ("%d%d%d%d",&x,&y,&w,&z);

        vecin[x].push_back(make_pair(y,z));
        vecin[y].push_back(make_pair(x,-z));
        realC[x].push_back(z);
        realC[y].push_back(-z);
        c[x][y]=w;
    }

    for(i=1;i<=n;i++)
        dist[i]=MULT;

    bellmanford(S);

    for(i=1;i<=n;i++)
        for(j=0;j<vecin[i].size();j++){
            int nod=vecin[i][j].first;
            int cost=vecin[i][j].second;

            vecin[i][j].second=dist[i]+cost-dist[nod];
        }

    flux();

    printf ("%d",ans);
    return 0;
}