Cod sursa(job #1514608)

Utilizator BogdanisarBurcea Bogdan Madalin Bogdanisar Data 31 octombrie 2015 12:53:44
Problema Flux maxim de cost minim Scor 70
Compilator cpp Status done
Runda Arhiva educationala Marime 2.37 kb
#include<iostream>
#include<fstream>
#include<vector>
#include<queue>
#include<bitset>

#define FOR(a,b,c) for(int a=b;a<=c;++a)
#define pb push_back
#define INF 100500000

// algoritmul cu Bellman-Ford optimizat

using namespace std;
ifstream f("fmcm.in");
ofstream g("fmcm.out");
int N,M,S,D;
int cap[360][360],cost[360][360],flux[360][360],dad[360],dist[360];
// cap[i][j]=capacitatea muchiei (i,j);
// flux[i][j]=fluxul muchiei (i,j) la un moment dat;
// cost[i][j]=costul muchiei (i,j);
// dist[i]=costul total de la sursa la nodul i la un moment dat
// dad[i]=nodul precedent nodului i la un moment dat

vector<int> v[360];
queue<int> Q;
bitset<360> in_queue;
// v=liste de adiacenta
// Q=coada folosita la algoritmul Bellman-Ford
// in_queue[i]=1 daca nodul i se afla in coada la acel moment

int Bellman_ford();

int main() {
    f>>N>>M>>S>>D;
    FOR (i,1,M) {
        int x,y,c,z;
        f>>x>>y>>c>>z;
        v[x].pb(y);
        v[y].pb(x);
        cap[x][y]=c;
        cost[x][y]=z;
        cost[y][x]=-z;
    }
    int rez=0,costdist;
    do { // cat timp gasesc un drum de avansare, adaug costul acestuia la costul total
        costdist=Bellman_ford();
        rez+=costdist;
    }
    while (costdist);
    g<<rez;
    f.close();g.close();
    return 0;
}

int Bellman_ford() { // caut un drum de avansare de cost minim
    FOR (i,1,N) {
        dist[i]=INF;
        dad[i]=-1;
    }
    in_queue.reset();
    dist[S]=0;
    Q.push(S);
    in_queue.set(S,1);
    while (!Q.empty()) {
        int nod=Q.front();
        Q.pop();
        vector<int>::iterator it;
        for (it=v[nod].begin();it<v[nod].end();++it) {
            if (cap[nod][*it]!=flux[nod][*it] && dist[nod]+cost[nod][*it]<dist[*it]) {
                dist[*it]=dist[nod]+cost[nod][*it];
                dad[*it]=nod;
                if (!in_queue.test(*it)) {
                    in_queue.set(*it,1);
                    Q.push(*it);
                }
            }
        }
        in_queue.set(nod,0);
    }
    if (dist[D]<INF-12500000) {
        int fluxc=INF;
        for (int i=D;i!=S;i=dad[i]) {
            fluxc=min(fluxc,cap[dad[i]][i]-flux[dad[i]][i]);
        }
        for (int i=D;i!=S;i=dad[i]) {
            flux[dad[i]][i]+=fluxc;
            flux[i][dad[i]]-=fluxc;
        }
        return fluxc*dist[D];
    }
    return 0;
}