Pagini recente » Cod sursa (job #810209) | Cod sursa (job #466399) | Cod sursa (job #567521) | Cod sursa (job #266452) | Cod sursa (job #1600760)
#include <fstream>
#include <iostream>
#include <vector>
#include <queue>
#include <bitset>
using namespace std;
ifstream fin("fmcm.in");
ofstream fout("fmcm.out");
const int NMAX = 350;
const int MMAX = 12500;
const int INF = 0x1fffffff;
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 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);
}
}
bool bellmanFord(int sursa, int dest, vector< vector<int> >& g) {
queue<int> q;
bitset<NMAX + 1> inQueue;
vector<int> dist(NMAX + 1, INF);
vector<int> cntQueue(NMAX + 1, 0);
bool isReachable = false;
q.push(sursa);
inQueue[sursa] = true;
dist[sursa] = 0;
before[sursa] = sursa;
cntQueue[sursa]++;
while(q.empty() == false) {
int node = q.front();
q.pop();
inQueue[node] = false;
for(int x : g[node]) {
int maxFlow = cap[node][x] - flow[node][x];
/* Nu ne intereseaza decat sa gasim un drum care poate fi ameliorat dpdv al fluxului, dar sa fie
minim dpdv al costului. Prima data cand se intalneste un flow > 0 si dist[x] = INF adica mai mare ca dist[node] + cost
Daca exista un drum de ameliorare pentru flux de la sursa la destinatie,
nu va fi impedicata gasirea lui de conditia dist[node] + cost < dist[x]*/
if(maxFlow > 0 && dist[node] + cost[node][x] < dist[x]) {
before[x] = node;
dist[x] = dist[node] + cost[node][x];
if(cntQueue[x] == n) {
cout << "Ciclu negativ" << '\n';
return false;
}
if(inQueue[x] == false) {
q.push(x);
inQueue[x] = true;
cntQueue[x]++;
}
if(x == dest) isReachable = true;
}
}
}
return isReachable;
}
void solve(int start, int dest, vector< vector<int> >& g) {
/* La fiecare pas gasim un drum de la sursa la destinatie, unde se mai poate creste fluxul */
/* Singura diferenta este ca acum vom lua acest drum ca fiind cel de cost minim */
while(bellmanFord(start, dest, g)) {
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;
while(before[x] != x) {
flow[before[x]][x] += maxFlow;
flow[x][before[x]] -= maxFlow;
minCost += maxFlow * cost[before[x]][x];
x = before[x];
}
}
}
int main() {
read();
solve(source, dest, g);
fout << minCost << '\n';
return 0;
}