Pagini recente » Cod sursa (job #2939831) | Cod sursa (job #2178231) | Cod sursa (job #1758768) | Cod sursa (job #1037417) | Cod sursa (job #3147282)
#include <stdio.h>
#include <vector>
// .... :( ma pis pe stl
#include <queue>
const int MAXN = 350;
const int MAXM = 12500;
const int INF = 1e9;
const int NIL = -1;
int cap[MAXN][MAXN];
int cost[MAXN][MAXN];
std::vector<int> adj[MAXN];
int prev_dist[MAXN]; // distanta de la iteratia precedenta
int real_dist[MAXN]; // distanta pe costuri adevarate (scadem potentialele (prev_dist))
int dist[MAXN]; // distanta pe costuri reduse
int par[MAXN]; // parintele in arborele parcurgerii djikstra
// bellman-ford
void init_potentials( int n, int src ){
int u;
std::queue<int> q( { src } );
for( u = 0 ; u < n ; u++ )
dist[u] = +INF;
dist[src] = 0;
while( !q.empty() ){
u = q.front();
q.pop();
for( int v : adj[u] )
if( cap[u][v] && dist[u] + cost[u][v] < dist[v] ){
dist[v] = dist[u] + cost[u][v];
q.push( v );
}
}
for( u = 0 ; u < n ; u++ )
prev_dist[u] = dist[u];
}
// djikstra
bool find_path( int n, int src, int dest ){
// nu facem cu set, pentru ca chiar daca nu trebuie sa iteram
// peste elementele gresite set are constanta mai mare (heap vs RB tree)
int u, aux;
std::pair<int, int> top;
std::priority_queue<std::pair<int, int>> pq;
for( u = 0 ; u < n ; u++ )
dist[u] = +INF;
dist[src] = 0;
par[src] = NIL;
pq.push( std::make_pair( 0, src ) );
while( !pq.empty() ){
top = pq.top();
pq.pop();
if( dist[top.second] == -top.first ){
u = top.second;
for( int v : adj[u] )
if( cap[u][v] ){
aux = cost[u][v] + prev_dist[u] - prev_dist[v]; // folosim prev_dist[] ca potentiale
if( dist[u] + aux < dist[v] ){
par[v] = u;
dist[v] = dist[u] + aux;
pq.push( std::make_pair( -dist[v], v ) );
}
}
}
}
// get real_dist[] as to not mess up prev_dist[]
for( u = 0 ; u < n ; u++ )
real_dist[u] = dist[u] + prev_dist[u] - prev_dist[src];
// now we can safely overwrite
for( u = 0 ; u < n ; u++ )
prev_dist[u] = real_dist[u];
return dist[dest] < +INF;
}
int main(){
FILE *fin = fopen( "fmcm.in", "r" );
FILE *fout = fopen( "fmcm.out", "w" );
int n, m, src, dest, i, a, b, flow, flow_cost, augment_flow, augment_cost;
fscanf( fin, "%d%d%d%d", &n, &m, &src, &dest );
src--;
dest--;
for( i = 0 ; i < m ; i++ ){
fscanf( fin, "%d%d", &a, &b );
a--;
b--;
adj[a].push_back( b );
adj[b].push_back( a );
fscanf( fin, "%d%d", &cap[a][b], &cost[a][b] );
cost[b][a] = -cost[a][b];
}
flow = flow_cost = 0;
init_potentials( n, src );
while( find_path( n, src, dest ) ){
// now we augment
augment_flow = +INF;
augment_cost = 0;
for( a = dest ; par[a] != NIL ; a = par[a] ){
augment_flow = cap[par[a]][a] < augment_flow ? cap[par[a]][a] : augment_flow;
augment_cost += cost[par[a]][a];
}
flow += augment_flow;
flow_cost += augment_flow * augment_cost;
for( a = dest ; par[a] != NIL ; a = par[a] ){
cap[par[a]][a] -= augment_flow;
cap[a][par[a]] += augment_flow;
}
}
fprintf( fout, "%d\n", flow_cost );
fclose( fin );
fclose( fout );
return 0;
}