Cod sursa(job #1557680)

Utilizator Liviu98Dinca Liviu Liviu98 Data 27 decembrie 2015 23:11:30
Problema Flux maxim de cost minim Scor 70
Compilator cpp Status done
Runda Arhiva educationala Marime 3.66 kb
/*
   Flux maxim de cost minim
   Complexitate:O(N*M2*logN) pentru 100 pct
   D. Liviu
*/
#include <iostream>
#include <stdio.h>
#include <deque>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <cstring>
#define NMax 352
using namespace std;
const int long long Infinit=999999;
vector<int> Graf[NMax];
set<pair<int,int> > Heap;
int Cost[NMax][NMax],Capacitate[NMax][NMax],Flux[NMax][NMax];
int tata[NMax],Distance[NMax];
bool InCoada[NMax];
queue<int> Q;
int N,M,Sursa,Destinatie,capacitate,x,y,z;

void Read()
{
    scanf("%d%d%d%d",&N,&M,&Sursa,&Destinatie);
    for(int i=1;i<=M;i++)
    {
        scanf("%d%d%d%d",&x,&y,&capacitate,&z);
        Graf[x].push_back(y);
        Graf[y].push_back(x);
        Capacitate[x][y]=capacitate;
        Cost[x][y]=Cost[x][y]+z;
        Cost[y][x]=Cost[y][x]-z;
    }
}

inline void BellManFord(int Sursa,int Destinatie)
{
    memset(Distance,Infinit,sizeof(Distance));
    Q.push(Sursa);
    Distance[Sursa]=0;
    InCoada[Sursa]=true;

    while(Q.empty()==false)
    {
        int nod=Q.front();
        Q.pop();
        InCoada[nod]=false;
        for(int i=0;i<Graf[nod].size();i++)
            if(Distance[Graf[nod][i]]>Distance[nod]+Cost[nod][Graf[nod][i]] && Capacitate[nod][Graf[nod][i]]>Flux[nod][Graf[nod][i]])
            {
                Distance[Graf[nod][i]]=Distance[nod]+Cost[nod][Graf[nod][i]];
                if(InCoada[Graf[nod][i]]==false)
                {
                    InCoada[Graf[nod][i]]=true;
                    Q.push(Graf[nod][i]);

                }}}
}

void Initialization(int Sursa,int Destinatie)
{
    for(int nod=1;nod<=N;nod++)
        for(int i=0;i<Graf[nod].size();i++)
            if(Distance[nod]!=Infinit && Distance[Graf[nod][i]]!=Infinit)
              Cost[nod][Graf[nod][i]]=Cost[nod][Graf[nod][i]]+(Distance[nod]-Distance[Graf[nod][i]]);
    memset(Distance,Infinit,sizeof(Distance));
    memset(tata,0,sizeof(tata));
}

bool Dijkstra(int Sursa,int Destinatie)
{
    Initialization(Sursa,Destinatie);
    Heap.insert(make_pair(0,Sursa));
     Distance[Sursa]=0;
    while(Heap.empty()==false)
    {
        int cost=(*Heap.begin()).first;
        int nod=(*Heap.begin()).second;
        Heap.erase(Heap.begin());
        if(Distance[nod]!=cost) continue;
        for(int i=0;i<Graf[nod].size();i++)
        if(Distance[Graf[nod][i]]>Distance[nod]+Cost[nod][Graf[nod][i]] && Capacitate[nod][Graf[nod][i]]>Flux[nod][Graf[nod][i]])
            {
                Distance[Graf[nod][i]]=Distance[nod]+Cost[nod][Graf[nod][i]];
                tata[Graf[nod][i]]=nod;
                Heap.insert(make_pair(Distance[Graf[nod][i]],Graf[nod][i]));
            }
    }
    return Distance[Destinatie]<Infinit;
}

long long EdmondsKarp(int Sursa,int Destinatie)
{
    long long CostFlow=0,flow=0;
    int FlowMin,DistanceFlow=Distance[Destinatie];

    while(Dijkstra(Sursa,Destinatie))
    {

        FlowMin=Infinit;
        for(int nod=Destinatie;nod!=Sursa;nod=tata[nod])
            FlowMin=min(FlowMin,(Capacitate[tata[nod]][nod]-Flux[tata[nod]][nod]));

        for(int nod=Destinatie;nod!=Sursa;nod=tata[nod])
        {
            Flux[tata[nod]][nod]=Flux[tata[nod]][nod]+FlowMin;
            Flux[nod][tata[nod]]=Flux[nod][tata[nod]]-FlowMin;
        }

        flow=flow+FlowMin;
        DistanceFlow=DistanceFlow+Distance[Destinatie];
        CostFlow=CostFlow+FlowMin*DistanceFlow;
    }
    return CostFlow;
}

int main()
{
    freopen("fmcm.in","r",stdin);
    freopen("fmcm.out","w",stdout);
    Read();
    BellManFord(Sursa,Destinatie);
    printf("%d",EdmondsKarp(Sursa,Destinatie));
}