Pagini recente » Cod sursa (job #380058) | Cod sursa (job #1612920) | Cod sursa (job #2458181) | Cod sursa (job #785529) | Cod sursa (job #2875856)
#include <fstream>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;
ifstream fin("fmcm.in");
ofstream fout("fmcm.out");
#define DIM 350
#define INF (1LL << 30)
typedef pair<int, int> PII;
int n, m, S, D, total, CostMin;
bool sel[DIM + 1];
int dist[DIM + 1], t[DIM + 1];
int C[DIM + 1][DIM + 1], F[DIM + 1][DIM + 1], Cost[DIM + 1][DIM + 1];
vector <int> G[DIM + 1];
priority_queue <PII, vector<PII>, greater<PII>> PQ;
static inline void Bellman_Ford(int S) {
for(int i = 1; i <= n; i++)
dist[i] = INF;
dist[S] = 0;
queue<int> Q;
Q.push(S);
sel[S] = 1;
while(!Q.empty()) {
int nod = Q.front();
sel[nod] = 0;
Q.pop();
for(auto e : G[nod])
if(C[nod][e] > F[nod][e] && dist[e] > dist[nod] + Cost[nod][e]) {
dist[e] = dist[nod] + Cost[nod][e];
if(!sel[e]) {
sel[e] = 1;
Q.push(e);
}
}
}
}
static inline bool Dijkstra(int S, int D) {
for(int i = 1; i <= n; i++)
if(dist[i] != INF)
for(auto e : G[i])
if(dist[e] != INF)
Cost[i][e] += dist[i] - dist[e]; //fac toate costurile pozitive;
for(int i = 1; i <= n; i++)
dist[i] = INF;
for(int i = 1; i <= n; i++)
t[i] = 0;
dist[S] = 0;
PQ.push({0, S}); //retin distanta si nodul;
while(!PQ.empty()) {
int nod = PQ.top().second;
int c = PQ.top().first;
PQ.pop();
if(c > dist[nod])
continue;
for(auto e : G[nod])
if(C[nod][e] > F[nod][e] && dist[e] > Cost[nod][e] + dist[nod]) {
t[e] = nod;
dist[e] = Cost[nod][e] + dist[nod];
PQ.push({dist[e], e});
}
}
return (dist[D] != INF); //daca am ajuns la destinatie;
}
static inline void Flux_Maxim(int S, int D) {
total = dist[D];
for(int drum = Dijkstra(S, D); drum; drum = Dijkstra(S, D)) {
int fluxmin = INF;
int nod = D;
while(nod != S) {
fluxmin = min(fluxmin, C[t[nod]][nod] - F[t[nod]][nod]);
nod = t[nod];
}
nod = D;
while(nod != S) {
F[t[nod]][nod] += fluxmin;
F[nod][t[nod]] -= fluxmin;
nod = t[nod];
}
total += dist[D];
CostMin += total * fluxmin;
}
}
int main() {
fin >> n >> m >> S >> D;
for(int i = 1; i <= m; i++) {
int x, y, cap, c;
fin >> x >> y >> cap >> c;
G[x].push_back(y);
G[y].push_back(x);
C[x][y] = cap;
Cost[x][y] = c;
Cost[y][x] = -c;
}
//retin distantele minime de la S la restul nodurilor;
Bellman_Ford(S);
Flux_Maxim(S, D);
fout << CostMin;
return 0;
}