Pagini recente » Cod sursa (job #1416992) | Cod sursa (job #2862439) | Cod sursa (job #767895) | Cod sursa (job #1205002) | Cod sursa (job #2126402)
#include <iostream>
#include <fstream>
#include <cstring>
#define DMAX 360
#define INFIN 1<<30
using namespace std;
ifstream in("fmcm.in");
ofstream out("fmcm.out");
struct nod{
int val;
nod * urm;
}*v[DMAX];
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;
int costMaxim, costDrumTotal ;
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];
nod * deAdaugat1 = new nod;
deAdaugat1 -> val = y;
deAdaugat1 -> urm = v[x];
v[x] = deAdaugat1;
nod * deAdaugat2 = new nod;
deAdaugat2 -> val = x;
deAdaugat2 -> urm = v[y];
v[y] = deAdaugat2;
}
in.close();
}
void bellmann(){
for(int i = 1; i<= n; i++){
costDrum[i] = INFIN;
}
costDrum[S] = 0;//punctul de plecare
int coada[DMAX], primul, ultimul;
primul = ultimul = 1;
coada[1] = S;
bool pusInCoada[DMAX];
memset(pusInCoada, false, sizeof(pusInCoada));
pusInCoada[S] = true;
while (primul <= ultimul){
int actual = coada[primul];
nod * parcurg = v[actual];
pusInCoada[actual] = false;
primul++;
while(parcurg != NULL){
//pun conditia de capacitate ca sa rec prin nodurile care imi ofera o inbunatatire a costului
if(capacitate[actual][parcurg -> val] > flux[actual][parcurg -> val] && (costDrum[parcurg -> val] > costDrum[actual] + cost[actual][parcurg -> val])){
costDrum[parcurg -> val] = costDrum[actual] + cost[actual][parcurg -> val];
if(pusInCoada[parcurg -> val] == false){
coada[++ultimul] = parcurg -> val;
pusInCoada[parcurg -> val] = true;
}
}
parcurg = parcurg -> urm;
}
}
costDrumTotal = costDrum[D];
}
inline int tataElem(int poz){
return poz/2;
}
inline int fiuStanga(int poz){
return poz * 2;
}
inline int fiuDreapta(int poz){
return poz * 2 + 1;
}
void interschimbare(int a, int b){
swap(heap[a],heap[b]);
swap(pozNodInHeap[heap[a]], pozNodInHeap[heap[b]]);
}
inline void verificareDeasupra(int poz){
if(poz > 1){
if(costDrum[heap[poz]] < costDrum[heap[tataElem(poz)]]) {
interschimbare(poz, tataElem(poz));
verificareDeasupra(tataElem(poz));
}
}
}
inline void validareInJos(int poz){
int pozFiu = 0;
if(fiuStanga(poz) <= lgHeap){
pozFiu = fiuStanga(poz);
if((pozFiu + 1 <= lgHeap) && costDrum[heap[pozFiu]] > costDrum[heap[fiuDreapta(poz)]]){
pozFiu = fiuDreapta(poz);
}
if(costDrum[pozFiu] >= costDrum[heap[poz]]){
pozFiu = 0;
}
}
if(pozFiu != 0){
interschimbare(poz, pozFiu);
validareInJos(pozFiu);
}
}
void stergereDinHeap(int poz){
interschimbare(1,lgHeap);
lgHeap--;
validareInJos(poz);
}
void actualizareArcePozitiv(){
for(int i = 1; i <= n; i++){
if(costDrum[i] != INFIN){
nod * parcurg = v[i];
while(parcurg != NULL){
if(costDrum[parcurg -> val] != INFIN) {
cost[i][parcurg->val] += costDrum[i] - costDrum[parcurg->val];
}
parcurg = parcurg -> urm;
}
}
}
}
inline int Dijkstra(){
actualizareArcePozitiv();
for(int i = 1; i<= n; i++){
costDrum[i] = INFIN;
}
costDrum[S] = 0;
memset(tata, 0 , sizeof(tata));
tata[S] = -1;
//construiesc heapul, momentan nearanjat
for(int i = 1; i<= n; i++){
heap[i] = i;
pozNodInHeap[i] = i;
}
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];
stergereDinHeap(1);
nod * parcurg = v[nodMinim];
while (parcurg != NULL){
if(flux[nodMinim][parcurg -> val] < capacitate[nodMinim][parcurg -> val]){
if(costDrum[parcurg -> val] > costDrum[nodMinim] + cost[nodMinim][parcurg -> val]){
costDrum[parcurg -> val] = costDrum[nodMinim] + cost[nodMinim][parcurg -> val];
tata[parcurg -> val] = nodMinim;
verificareDeasupra(pozNodInHeap[parcurg -> val]);
}
}
parcurg = parcurg -> urm;
}
}
return (costDrum[D]!= INFIN) ? 1 : 0;
}
void fluxMaxim(){
costMaxim = 0;
for (bool existaDrumAmel = Dijkstra(); existaDrumAmel != 0; existaDrumAmel = 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];
costMaxim += costDrumTotal * FluxMaximDePus;
}
}
int main() {
citire();
bellmann();
//folosesc algoritmul lui bellmann pentru a calcula initial distantele minime
fluxMaxim();
out << costMaxim;
return 0;
}