Cod sursa(job #1688405)

Utilizator BugirosRobert Bugiros Data 13 aprilie 2016 14:37:54
Problema Flux maxim de cost minim Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 4.06 kb
#include <fstream>
#include <vector>
#include <queue>
using namespace std;

const int MAXN = 355;
const int INF = 1 << 30;

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

int n,sursa,destinatie;
int cost[MAXN][MAXN];//Atentie! Trebuie cu matrice de adiacenta deoarece trebuie costul dintre x si y in O(1)
int capacitate[MAXN][MAXN];//Atentie! Trebuie cu matrice de adiacenta deoarece trebuie capacitatea dintre x si y in O(1)

int flux, flux_maxim_de_cost_minim;

int dvechi[MAXN],dreal[MAXN];
vector<int> vecini[MAXN];

void citire()
{
    int m;
    in >> n >> m >> sursa >> destinatie;
    for(int i = 1;i <= m;++i)
    {
        int x,y,c,z;
        in >> x >> y >> c >> z;
        vecini[x].push_back(y);
        capacitate[x][y] = c;
        cost[x][y] = z;
        //se asociaza graful rezidual, o muchie noua intre y si x de cost -z si capacitate 0
        vecini[y].push_back(x);
        capacitate[y][x] = 0;
        cost[y][x] = -z;
    }
}

struct nod_dij
{
    int nod,cost;
    bool operator < (const nod_dij &b) const
    {
        return cost > b.cost;//heapul din std e de maxime
    }
};


int d[MAXN];
int tata[MAXN];

bool dijkstra()//intoarce adevarat daca am gasit drum de ameliorare
{
    for (int i = 1;i <= n;++i)
        d[i] = INF;
    d[sursa] = 0;
    dreal[sursa] = 0;
    priority_queue<nod_dij> heap;
    heap.push((nod_dij){sursa,0});
    while(!heap.empty())
    {
        int cst = heap.top().cost;
        int nod = heap.top().nod;
        heap.pop();
        if (d[nod] != cst)//inseamna ca a fost imbunatatit
            continue;
        for (unsigned int i = 0;i < vecini[nod].size();++i)
        {
            int vecin = vecini[nod][i];
            if (capacitate[nod][vecin] != 0)//orice muchie are capacitate nenula
            {
                int dist_nou = d[nod] + cost[nod][vecin] + dvechi[nod] - dvechi[vecin];
                if (dist_nou < d[vecin])
                {
                    d[vecin] = dist_nou;
                    dreal[vecin] = dreal[nod] + cost[nod][vecin];
                    tata[vecin] = nod;
                    heap.push((nod_dij){vecin,dist_nou});
                }
            }
        }
    }
    for (int i = 1;i <= n;++i)
        dvechi[i] = dreal[i];
    if (d[destinatie] == INF)
        return false;

    int influx = INF, cost_influx = 0;
    for (int aux = destinatie;aux != sursa;aux = tata[aux])
    {
        if (capacitate[ tata[aux] ][aux] < influx)
            influx = capacitate[ tata[aux] ][aux];
        cost_influx += cost[tata[aux]][aux];
    }
    flux += influx;
    flux_maxim_de_cost_minim += influx * dreal[destinatie];

    for (int aux = destinatie;aux != sursa;aux = tata[aux])
    {
        capacitate[tata[aux]][aux] -= influx;
        capacitate[aux][tata[aux]] += influx;
    }
    return true;
}


void creare_arce_pozitive()
//folosim Bellman-Ford pentru a crea toate arcele pozitive intrucat
//algoritmul lui Dijkstra nu e valid pe arce de cost negativ
{
    for (int i = 1;i <= n;++i)
        dvechi[i] = INF;
    dvechi[sursa] = 0;
    queue<int> coada;
    bool in_coada[MAXN] = {0};
    coada.push(sursa);
    in_coada[sursa] = true;
    while(!coada.empty())
    {
        int nod = coada.front();
        in_coada[nod] = false;
        coada.pop();
        for (unsigned int i = 0;i < vecini[nod].size();++i)
        {
            int vecin = vecini[nod][i];
            if(capacitate[nod][vecin] != 0)//orice muchie are capacitate nenula
            {
                if(dvechi[nod] + cost[nod][vecin] >= dvechi[vecin])
                    continue;
                dvechi[vecin] = dvechi[nod] + cost[nod][vecin];
                if (in_coada[vecin])
                    continue;
                in_coada[vecin] = true;
                coada.push(vecin);
            }
        }
    }
}

int main()
{
    citire();
    flux = flux_maxim_de_cost_minim = 0;
    creare_arce_pozitive();
    while(dijkstra())
        ;
    out << flux_maxim_de_cost_minim << '\n';
    return 0;
}