Pagini recente » Cod sursa (job #2122887) | Cod sursa (job #2793484) | Cod sursa (job #2237955) | Cod sursa (job #1964223) | Cod sursa (job #2961457)
// Complexitate O(N*M2*logN)
#include <bits/stdc++.h>
using namespace std;
ifstream f("fmcm.in");
ofstream g("fmcm.out");
int n, s, d, capacitate[351][351], cost[351][351], inQ[351], distVeche[351], dist[351], distNoua[351], parinte[351], raspuns;
vector<int> muchii[351];
queue<int>q;
priority_queue<pair<int, int> > pq;
void citire(), bellmandFord(), rezolvare(), afisare();
bool dijkstra();
int main()
{
citire();
rezolvare();
afisare();
return 0;
}
void afisare() {
g << raspuns;
g.close();
}
void rezolvare() {
bellmandFord();
while(dijkstra());
}
bool dijkstra() {
// Initial niciun nod nu e vizitat
for(int i = 0; i <= n; ++i)
dist[i] = 1000000000;
// Nodul sursa e vizitat si se afla la distanta 0
dist[s] = 0;
distNoua[s] = 0;
pq.push({0, s});
// Cat timp mai am elemente
while(!pq.empty()) {
int c = -pq.top().first;
int nod = pq.top().second;
pq.pop();
// Daca am trecut deja prin nod continuam
if(dist[nod] != c) {
continue;
}
// Verific pentru toti vecinii daca pot forma un drum mai bun din nodul curent
for(auto it : muchii[nod])
// Daca am capacitate pe muchie
if(capacitate[nod][it]) {
int d = c + cost[nod][it];
// Aduagam distVeche[nod] - distVeche[it] pentru a face costul pozitiv
d += distVeche[nod] - distVeche[it];
if(d < dist[it])
{
// In dist pastrez costul modificat care e numai pozitiv
dist[it] = d;
// In distNoua pastrez costul adevarat al drumului care poate fi si negativ
distNoua[it] = distNoua[nod] + cost[nod][it];
// Momentan cel mai bun drum pana la vecin este prin nod
parinte[it] = nod;
// Adaug in coada vecinul si costul drumului pana la el
pq.push({-dist[it], it});
}
}
}
// Distanta veche pentru pasul urmator e acum distanta noua
for(int i = 1; i <= n; ++i) {
distVeche[i] = distNoua[i];
}
// Daca nu am ajuns la destinatie ma opresc
if(dist[d] == 1000000000)
return false;
// Calculez fluxul pe care pot sa-l adaug pe drumul minim si costul
int flux = 1000000000, rasp = 0;
int nod = d;
while(nod != s) {
int p = parinte[nod];
flux = min(flux, capacitate[p][nod]);
rasp += cost[p][nod];
nod = p;
}
// Aduag la raspuns costul fluxului adaugat
raspuns += rasp * flux;
// Adaug fluxul pe drumul gasit
nod = d;
while(nod != s) {
int p = parinte[nod];
capacitate[p][nod] -= flux,
capacitate[nod][p] += flux;
nod = p;
}
// Am gasit un drum pe care pot adauga flux
return true;
}
// Calculez distanta minima de la sursa la toate nodurile
void bellmandFord() {
for(int i = 0; i <= n; ++i)
distVeche[i] = 1000000000;
q.push(s);
inQ[s] = 1;
distVeche[s] = 0;
while(!q.empty()) {
int nod = q.front();
inQ[nod] = 0;
q.pop();
for(auto vecin : muchii[nod])
if(capacitate[nod][vecin] && distVeche[nod] + cost[nod][vecin] < distVeche[vecin]) {
distVeche[vecin] = distVeche[nod] + cost[nod][vecin];
if(!inQ[vecin]) {
q.push(vecin);
inQ[vecin] = 1;
}
}
}
}
void citire() {
int m;
f >> n >> m >> s >> d;
while(m--) {
int x, y, c, z;
f >> x >> y >> c >> z;
muchii[x].push_back(y);
muchii[y].push_back(x);
capacitate[x][y] = c;
cost[x][y] = z;
cost[y][x] = -z;
}
f.close();
}