Pagini recente » Cod sursa (job #2850616) | Cod sursa (job #2684276) | Cod sursa (job #1086391) | Cod sursa (job #2807697) | Cod sursa (job #2127421)
#include <iostream>
#include <fstream>
#include <cstring>
#include <vector>
#include <queue>
#define DMAX 356
#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;
long long costMaxim;
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(){
for(int i = 1; i<= n; i++){
costDrum[i] = INFIN;
}
costDrum[S] = 0;//punctul de plecare
coada.push(S);
while (!coada.empty()){
int actual = coada.front();
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];
coada.push(*vecin);
}
}
}
costDrumTotal = costDrum[D];
}
inline 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){
int tataElem = poz / 2;
if(costDrum[heap[poz]] < costDrum[heap[tataElem]]) {
interschimbare(poz, tataElem);
verificareDeasupra(tataElem);
}
}
}
inline void validareInJos(int poz){
int pozFiu = 0;
int fiuStanga = poz * 2;
if(fiuStanga <= lgHeap){
pozFiu = fiuStanga;
int fiuDreapta = fiuStanga + 1;
if((fiuDreapta <= lgHeap) && costDrum[heap[fiuStanga]] > costDrum[heap[fiuDreapta]]){
pozFiu = fiuDreapta;
}
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){
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;
heap[i] = i;
pozNodInHeap[i] = i;
tata[i] = 0;
}
costDrum[S] = 0;
tata[S] = -1;
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);
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(){
costMaxim = 0;
while(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 += (long long)costDrumTotal * FluxMaximDePus;
}
}
int main() {
citire();
bellmann();
//folosesc algoritmul lui bellmann pentru a calcula initial distantele minime
fluxMaxim();
out << costMaxim;
return 0;
}