Pagini recente » Istoria paginii utilizator/mateiasgt | Cod sursa (job #3361310)
#include <fstream>
#include <vector>
#include <queue>
using namespace std;
ifstream cin("fmcm.in");
ofstream cout("fmcm.out");
const int NMAX = 350;
const int MMAX = 12500;
const int INF = 1e9;
struct maxFlow{
int n;
int source, sink;
struct edge{
int x, y;
int cap, cost;
int w;
};
edge e[2 * MMAX + 5];
vector<int> v[NMAX + 5];
int numberOfEdges = 0;
int pot[NMAX + 5];
int d[NMAX + 5];
void init(int x, int s, int t)
{
n = x;
source = s;
sink = t;
}
void addEdge(int x, int y, int z, int c)
{
numberOfEdges++;
e[numberOfEdges].cap = z;
v[x].push_back(numberOfEdges);
e[numberOfEdges].x = x; e[numberOfEdges].y = y;
e[numberOfEdges].cost = c;
numberOfEdges++;
e[numberOfEdges].cap = 0;
v[y].push_back(numberOfEdges);
e[numberOfEdges].x = y; e[numberOfEdges].y = x;
e[numberOfEdges].cost = -c;
}
void bellmanFord()
{
//Valorile initiale ale vectorului d (si implicit ale vectorului de potentiale).
for(int i = 1; i <= n; i++)
d[i] = INF;
d[source] = 0;
for(int times = 1; times <= n; times++)
for(int i = 1; i <= numberOfEdges; i++)
if(e[i].cap && d[e[i].x] != INF)
d[e[i].y] = min(d[e[i].y], d[e[i].x] + e[i].cost);
for(int i = 1; i <= n; i++)
pot[i] = d[i];
}
void buildW()
{
for(int i = 1; i <= numberOfEdges; i++)
e[i].w = (e[i].cost + pot[e[i].x] - pot[e[i].y]);
}
int prev[NMAX + 5];
bool getAugmentingPath()
{
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;
for(int i = 1; i <= n; i++)
d[i] = INF;
d[source] = 0;
prev[source] = 0;
pq.push({0, source});
int nod, cost;
bool reachedSink = 0;
while(!pq.empty())
{
cost = pq.top().first;
nod = pq.top().second;
pq.pop();
if(nod == sink)
reachedSink = 1;
if(cost == d[nod])
{
for(int& it : v[nod])
if(e[it].cap && cost + e[it].w < d[e[it].y])
{d[e[it].y] = cost + e[it].w; prev[e[it].y] = it; pq.push({d[e[it].y], e[it].y});}
}
}
return reachedSink;
}
int maxFlow = 0;
int minCost = 0;
void pushFlow()
{
int nod = sink;
int mini = INF;
while(prev[nod])
{
mini = min(mini, e[prev[nod]].cap);
nod = (e[prev[nod]].x == nod ? e[prev[nod]].y : e[prev[nod]].x);
}
nod = sink;
while(prev[nod])
{
e[prev[nod]].cap -= mini;
e[((prev[nod] & 1) ? prev[nod] + 1 : prev[nod] - 1)].cap += mini; //Crestem capacitatea pe muchia inversa.
minCost += (mini * e[prev[nod]].cost);
nod = (e[prev[nod]].x == nod ? e[prev[nod]].y : e[prev[nod]].x);
}
maxFlow += mini;
}
int getMinCost()
{
bellmanFord();
buildW();
while(getAugmentingPath())
{
pushFlow();
for(int i = 1; i <= n; i++)
pot[i] += d[i];
buildW();
}
return minCost;
}
};
maxFlow flow;
int n, m, s, d;
void readInput()
{
cin >> n >> m >> s >> d;
int x, y, z, c;
flow.init(n, s, d);
for(int i = 1; i <= m; i++)
{
cin >> x >> y >> z >> c;
flow.addEdge(x, y, z, c);
}
}
int main()
{
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
readInput();
cout << flow.getMinCost();
return 0;
}