Pagini recente » Cod sursa (job #450079) | Cod sursa (job #2823495) | Cod sursa (job #2764485) | Cod sursa (job #1539841) | Cod sursa (job #2127506)
#include <iostream>
#include <fstream>
#include <cstring>
#include <vector>
#include <queue>
#define DMAX 356
#define INFIN 0x3f3f3f3f
using namespace std;
ifstream in("fmcm.in");
ofstream out("fmcm.out");
int n, m;//date de intrare
int S, D;
int capacitate[DMAX][DMAX], cost[DMAX][DMAX];
int flux[DMAX][DMAX];
int costDrum[DMAX],tata[DMAX];
int heap[DMAX],pozNodInHeap[DMAX], lgHeap;
long long costMinim;
int costDrumTotal ;
vector <int> graf[DMAX];
vector <int> ::iterator vecin;
queue <int> coada;
void citire(){
in >> n >> m >> S >> D;
for(int i = 1; i <= m; i++){
int x, y;
in >> x >> y;
in >> capacitate[x][y];
in >> cost[x][y];
cost[y][x] = -cost[x][y];
graf[x].push_back(y);
graf[y].push_back(x);
}
in.close();
}
void bellmann(){
bool pusInCoada[DMAX];
for(int i = 1; i<= n; i++){
costDrum[i] = INFIN;
pusInCoada[i] = false;
}
costDrum[S] = 0;//punctul de plecare
coada.push(S);
pusInCoada[S] = true;
while (!coada.empty()){
int actual = coada.front();
pusInCoada[actual] = false;
coada.pop();
for(vecin = graf[actual].begin(); vecin != graf[actual].end(); vecin++){
//pun conditia de capacitate ca sa rec prin nodurile care imi ofera o inbunatatire a costului
if(capacitate[actual][*vecin] > flux[actual][*vecin] && costDrum[*vecin] > costDrum[actual] + cost[actual][*vecin]){
costDrum[*vecin] = costDrum[actual] + cost[actual][*vecin];
if(pusInCoada[*vecin] == false){
coada.push(*vecin);
pusInCoada[*vecin] = true;
}
}
}
}
costDrumTotal = costDrum[D];
}
void interschimbare(int a, int b){
int aux = heap[a];
heap[a] = heap[b];
heap[b] = aux;
pozNodInHeap[heap[a]] = a;
pozNodInHeap[heap[b]] = b;
}
void verificareDeasupra(int poz){
if(poz > 1){
int tataElem = poz / 2;
if(costDrum[heap[poz]] < costDrum[heap[tataElem]]) {
interschimbare(poz, tataElem);
verificareDeasupra(tataElem);
}
}
}
void validareInJos(int poz){
int pozFiu = poz * 2;//iau ca fiu nodul din stanga
if(pozFiu <= lgHeap){
int fiuDreapta = pozFiu + 1;
if((fiuDreapta <= lgHeap) && costDrum[heap[pozFiu]] > costDrum[heap[fiuDreapta]]){
pozFiu = fiuDreapta;
}
if(costDrum[heap[pozFiu]] < costDrum[heap[poz]]){
interschimbare(pozFiu, poz);
validareInJos(pozFiu);
}
}
}
void actualizareArcePozitiv(){
for(int i = 1; i <= n; i++){
if(costDrum[i] != INFIN){
for(vecin = graf[i].begin(); vecin != graf[i].end(); vecin++){
if(costDrum[*vecin] != INFIN) {
cost[i][*vecin] += costDrum[i] - costDrum[*vecin];
}
}
}
}
}
bool Dijkstra(){
actualizareArcePozitiv();
for(int i = 1; i<= n; i++){
costDrum[i] = INFIN;
tata[i] = 0;
heap[i] = i;
pozNodInHeap[i] = i;
}
costDrum[S] = 0;
// tata[S] = -1;
//construiesc heapul, momentan nearanjat
interschimbare(1,S);//sursa va fi primul nod, oricum el este cel mai aproape de sursa
lgHeap = n;//in heap am n elemente;
while(lgHeap != 0 && (costDrum[heap[1]] != INFIN)){//cat timp avem un drum scurt
int nodMinim = heap[1];
interschimbare(1,lgHeap);
lgHeap--;
validareInJos(1);
for(vecin = graf[nodMinim].begin(); vecin != graf[nodMinim].end(); vecin++){
if(flux[nodMinim][*vecin] < capacitate[nodMinim][*vecin]){
if(costDrum[*vecin] > costDrum[nodMinim] + cost[nodMinim][*vecin]){
costDrum[*vecin] = costDrum[nodMinim] + cost[nodMinim][*vecin];
tata[*vecin] = nodMinim;
verificareDeasupra(pozNodInHeap[*vecin]);
}
}
}
}
return costDrum[D]!= INFIN;
}
void fluxMaxim(){
costMinim = 0;
for (; Dijkstra();){
int FluxMaximDePus = INFIN;
//aflu capacitatea maxima pe care o pot pompa pe arcele din drum
for(int intoarcere = D; intoarcere != S; intoarcere = tata[intoarcere]){
int temp1 = capacitate[tata[intoarcere]][intoarcere];
int temp2 = flux[tata[intoarcere]][intoarcere];
FluxMaximDePus = min(temp1 - temp2, FluxMaximDePus);
}
//saturez drumul de ameliorare
for(int intoarcere = D; intoarcere != S; intoarcere = tata[intoarcere]){
flux[tata[intoarcere]][intoarcere] += FluxMaximDePus;
flux[intoarcere][tata[intoarcere]] -= FluxMaximDePus;
}
costDrumTotal += costDrum[D];
costMinim+= (long long)costDrumTotal * FluxMaximDePus;
}
}
int main() {
citire();
bellmann();
//folosesc algoritmul lui bellmann pentru a calcula initial distantele minime
fluxMaxim();
out << costMinim;
return 0;
}