Pagini recente » Cod sursa (job #2637224) | Cod sursa (job #2433292) | Cod sursa (job #1907787) | Cod sursa (job #78802) | Cod sursa (job #1601727)
#include <fstream>
#include <iostream>
#include <vector>
#include <queue>
#include <bitset>
#include <cstring>
using namespace std;
ifstream fin("fmcm.in");
ofstream fout("fmcm.out");
#define pair pair<int,int>
const int NMAX = 350;
const int MMAX = 12500;
const int INF = 0x7fffffff;
int n; int m; int source; int dest;
int cap[NMAX + 1][NMAX + 1];
int flow[NMAX + 1][NMAX + 1];
int cost[NMAX + 1][NMAX + 1];
/* res graph = cost - flow */
vector< vector<int> > g(NMAX + 1, vector<int>(0));
int before[NMAX + 1];
int oldD[NMAX + 1]; int realD[NMAX + 1];
priority_queue< pair , vector< pair > , greater< pair > > pq;
int minCost;
void read() {
fin >> n >> m >> source >> dest;
for(int i = 1; i <= m; ++i) {
int x; int y; int capacity; int c;
fin >> x >> y >> capacity >> c;
cap[x][y] = capacity;
cost[x][y] = c;
cost[y][x] = -c;
g[x].push_back(y);
g[y].push_back(x);
}
}
void bellmanFord(int sursa, int dest, vector< vector<int> >& g) {
queue<int> q;
bitset<NMAX + 1> inQueue;
for(int i = 1; i <= n; ++i)
oldD[i] = INF;
q.push(sursa);
inQueue[sursa] = true;
oldD[sursa] = 0;
while(q.empty() == false) {
int node = q.front();
q.pop();
inQueue[node] = false;
for(int x : g[node])
if(cap[node][x] && oldD[node] + cost[node][x] < oldD[x]) {
oldD[x] = oldD[node] + cost[node][x];
if(inQueue[x] == false) {
q.push(x);
inQueue[x] = true;
}
}
}
}
bool dijkstra(int start, int dest, vector< vector<int> >& g) {
vector<int> dist(NMAX + 1, INF);
/* We use this to calculate the real distance realD. We don t need this calculations. */
pq.push({0, start});
dist[start] = realD[start] = 0;
before[start] = start;
while(pq.empty() == false) {
int node = pq.top().second;
int dst = pq.top().first;
pq.pop();
if(dst < dist[node]) continue;
for(int x : g[node]) {
int maxFlow = cap[node][x] - flow[node][x];
if(maxFlow <= 0) continue;
int d = dist[node] + cost[node][x] + oldD[node] - oldD[x];
if(d >= dist[x]) continue;
dist[x] = d;
pq.push({dist[x], x});
before[x] = node;
realD[x] = realD[node] + cost[node][x];
}
}
return (dist[dest] != INF);
}
void solve(int start, int dest, vector< vector<int> >& g) {
/* Precalculez distantele cu BellmanFord apoi asociez muchiei x->y costul
cost[x][y] + oldD[x] - oldD[y] > 0. Drumurile minime nu se modifica. Se demonstreaza prin RA.
*/
bellmanFord(start, dest, g);
/* Desi nu a fost luat in considerare si costul invers in bellmanforst, din ecuatii da si el pozitiv
cost[j][i] = -cost[i][j] + oldD[j] - oldD[i], oldD[j] > oldD[i] + cost[i][j] */
while(dijkstra(start, dest, g)) {
memcpy(oldD, realD, sizeof(oldD));
int x = dest; int maxFlow = INF;
while(before[x] != x) {
maxFlow = min(maxFlow, cap[before[x]][x] - flow[before[x]][x]);
x = before[x];
}
x = dest;
minCost += maxFlow * realD[dest];
while(before[x] != x) {
flow[before[x]][x] += maxFlow;
flow[x][before[x]] -= maxFlow;
x = before[x];
}
}
}
int main() {
ios_base::sync_with_stdio(false);
read();
solve(source, dest, g);
fout << minCost << '\n';
return 0;
}