Pagini recente » Cod sursa (job #2157935) | Cod sursa (job #972662) | Cod sursa (job #292419) | Cod sursa (job #3185621) | Cod sursa (job #2573950)
#include <fstream>
#include <vector>
#include <queue>
using namespace std;
ifstream in( "fmcm.in" );
ofstream out( "fmcm.out" );
const int N_MAX = 350;
const int INF = 1000000000;
struct comp {
bool operator()( const pair<int, int> &a, const pair<int, int> &b ) {
return a.second > b.second;
}
};
int N, M, Source, Dest;
vector<int> Edges[N_MAX + 1];
int Capacity[N_MAX + 1][N_MAX + 1], Cost[N_MAX + 1][N_MAX + 1], Flow[N_MAX + 1][N_MAX + 1];
priority_queue<pair<int, int>, vector<pair<int, int>>, comp> Q;
int D[N_MAX + 1];
int oldD[N_MAX + 1];
int realD[N_MAX + 1];
int T[N_MAX + 1];
bool inQ[N_MAX + 1];
void SPFA() {
for ( int i = 1; i <= N; i++ )
oldD[i] = INF;
oldD[Source] = 0;
queue<int> Q;
Q.push( Source ), inQ[Source] = true;
while ( !Q.empty() ) {
int x = Q.front();
Q.pop();
inQ[x] = false;
for ( auto y : Edges[x] )
if ( Capacity[x][y] ) { //! sa fie arc din graful normal
int cost = Cost[x][y];
if ( oldD[x] + cost < oldD[y] ) {
oldD[y] = oldD[x] + cost;
if ( !inQ[y] ) {
Q.push( y );
inQ[y] = true;
}
}
}
}
}
bool dijkstra() {
for ( int i = 1; i <= N; i++ )
D[i] = INF;
D[Source] = 0, realD[Source] = 0;
Q.push( pair<int, int>( Source, D[Source] ) );
while ( !Q.empty() ) {
int x = Q.top().first, cst = Q.top().second;
Q.pop();
if ( D[x] != cst )
continue;
for ( auto y : Edges[x] )
if( Capacity[x][y] > Flow[x][y] ) {
int cost = Cost[x][y];
int newD = D[x] + oldD[x] - oldD[y];
if ( newD + cost < D[y] ) {
D[y] = newD + cost;
realD[y] = realD[x] + cost;
T[y] = x;
Q.push( pair<int, int>( y, D[y] ) );
}
}
}
if ( D[Dest] == INF ) //daca nu am ajuns in Dest, nu mai avem ce ameliora, avem flux maxim de cost minim
return false;
return true;
}
int main() {
int x, y, cap, cost;
in >> N >> M >> Source >> Dest;
for ( int i = 1; i <= M; ++i ) {
in >> x >> y >> cap >> cost;
Edges[x].push_back( y );
Capacity[x][y] = cap;
Cost[x][y] = cost;
//formam graful rezidual: se adauga arcele inverse, cu capacitatea 0 si costul -cost
Edges[y].push_back( x );
Capacity[y][x] = 0;
Cost[y][x] = -cost;
}
//graful rezidual contine arce de cost negativ, deci aplicam initial algoritmul Bellman-Ford, dar pe graful normal
SPFA();
int maxflow = 0, mincost = 0;
while ( dijkstra() ) {
int flowgap = INF;
for ( int x = Dest; x != Source; x = T[x] ) //parcurgem invers lantul de ameliorare si determinam capacitatea reziduala minima
flowgap = min( flowgap, Capacity[T[x]][x] - Flow[T[x]][x] );
//amelioram fluxul lantului
for ( int x = Dest; x != Source; x = T[x] ) {
mincost += Cost[T[x]][x] * flowgap;
Flow[T[x]][x] += flowgap; //se creste fluxul pe arcele retelei de transport
Flow[x][T[x]] -= flowgap; //se scade fluxul pe arcele grafului rezidual
}
maxflow += flowgap;
for ( int i = 1; i <= N; ++i )
oldD[i] = realD[i];
}
out << mincost;
return 0;
}