Pagini recente » Cod sursa (job #1931173) | Istoria paginii runda/boji_round2 | Cod sursa (job #819494) | Cod sursa (job #1890454) | Cod sursa (job #1464227)
#include <iostream>
#include <fstream>
#include <vector>
#include <queue>
using namespace std;
ifstream fin ("fmcm.in") ;
ofstream fout ("fmcm.out") ;
const int Nmax = 350 + 1 ;
const int Mmax = 12500 + 1 ;
const int INF = 10000 + 1 ;
vector < int > G[Nmax] ;
int Capacity[Nmax][Nmax] ;
int Flow[Nmax][Nmax] ;
int Cost[Nmax][Nmax] ;
queue <int> Q ;
int dist[Nmax] ;
bool in_queue[Nmax] ;
priority_queue< pair < int , int > , vector < pair < int , int > > , greater < pair < int , int > > > MinHeap ;
int tata[Nmax] ;
int N , M ;
void addEdge ( int x , int y , int cap , int c )
{
G[x].push_back(y) ;
G[y].push_back(x) ;
Capacity[x][y] = cap ;
Capacity[y][x] = 0 ;
Cost[x][y] = c ;
Cost[y][x] = -c ;
}
bool Bellman_Ford(int S, int T)
{
for ( int i = 1 ; i <= N ; ++ i )
{
dist[i] = INF ;
in_queue[i] = false ;
tata[i] = 0 ;
}
Q.push(S) ;
in_queue[S] = false;
dist[S] = 0 ;
tata[S] = S ;
while ( !Q.empty() )
{
int nod = Q.front() ;
in_queue[nod] = false ;
Q.pop() ;
for ( vector < int > :: iterator son = G [nod].begin () ; son != G [nod].end() ; son ++ )
{
if ( ( Capacity[nod][*son] > Flow[nod][*son]) && dist[*son] > dist[nod] + Cost[nod][*son] )
{
dist[*son] = dist[nod] + Cost[nod][*son] ;
tata[*son] = nod ;
if ( !in_queue[*son] )
{
in_queue[*son] = true ;
Q.push(*son) ;
}
}
}
}
return ( dist[T] != INF ) ;
}
void updateCosts()
{
for ( int i = 1 ; i <= N ; ++ i )
{
if ( dist[i] != INF )
{
for ( vector < int > :: iterator son = G [i].begin () ; son != G [i].end() ; son ++ )
{
if ( dist[*son] != INF )
Cost[i][*son] += dist[i] - dist[*son];
}
}
}
}
int Dijkstra ( int S , int T )
{
updateCosts() ; // facem costurile pozitive
for ( int i = 1 ; i <= N ; ++ i )
{
dist[i] = INF ;
in_queue[i] = false ;
tata[i] = 0 ;
}
MinHeap.push({0, S}) ;
dist[S] = 0 ;
tata[S] = S ;
while ( !MinHeap.empty() )
{
int nod = MinHeap.top().second ;
int auxD = MinHeap.top().first ;
MinHeap.pop() ;
if ( auxD != dist[nod] )
continue ;
for ( vector < int > :: iterator son = G [nod].begin () ; son != G [nod].end() ; son ++ )
{
if (( Capacity[nod][*son] > Flow[nod][*son]) && dist[*son] > dist[nod] + Cost[nod][*son])
{
dist[*son] = dist[nod] + Cost[nod][*son];
tata[*son] = nod;
MinHeap.push({dist[*son], *son});
}
}
}
return ( dist[T] != INF ) ;
}
pair < int , long long > minCostMaxFlow ( int S, int T )
{
int flow = 0 ;
long long costFlow = 0 ;
long long totalDist = 0 ;
Bellman_Ford ( S , T ) ;
totalDist = dist[T] ;
while ( Dijkstra( S , T ) )
{
int fmin = INF ;
int nod = T ;
while (nod != S)
{
fmin = min ( fmin , Capacity[ tata[nod] ][nod] - Flow[ tata[nod] ][nod] ) ;
nod = tata[nod] ;
}
nod = T ;
while ( nod != S )
{
Flow[ tata[nod] ][nod] += fmin ;
Flow[nod][ tata[nod] ] -= fmin ;
nod = tata[nod] ;
}
flow += fmin ;
totalDist += dist[T] ;
costFlow += (long long)fmin * totalDist ;
}
return make_pair ( flow , costFlow ) ;
}
int main()
{
int S , T ;
fin >> N >> M >> S >> T ;
for ( int i = 0 ; i < M ; ++ i )
{
int x, y, cap, cost ;
fin >> x >> y >> cap >> cost ;
addEdge ( x , y , cap , cost ) ;
}
fout << minCostMaxFlow(S, T).second << "\n" ;
return 0;
}