Pagini recente » Cod sursa (job #2653465) | Cod sursa (job #126603) | Cod sursa (job #644072) | Cod sursa (job #2557020) | Cod sursa (job #2416452)
#include <iostream>
#include <fstream>
#include <climits>
#include <bitset>
#include <vector>
#include <queue>
using namespace std;
int const nmax = 350;
int const DIM = 10000;
ifstream in("fmcm.in");
ofstream out("fmcm.out");
struct Edge
{
int to;
int rev;
int flow;
int cap;
int cost;
};
vector<Edge> g[1 + nmax];
struct Node
{
int node;
int d;
bool operator> (Node other) const
{
return d > other.d;
}
};
int n, m, src, dest;
int dist[1 + nmax], distdij[1 + nmax];
int prio[1 + nmax];
bitset<1 + nmax> vis;
int prevnode[1 + nmax], prevedge[1 + nmax], pushflow[1 + nmax];
char buff[DIM];
int poz;
void read(int &nr)
{
nr = 0;
char sgn = '+';
while (buff[poz] < '0' || buff[poz] > '9')
{
sgn = buff[poz];
if (++poz == DIM)
in.read(buff, DIM), poz = 0;
}
while ('0' <= buff[poz] && buff[poz] <= '9')
{
nr = nr * 10 + buff[poz] - '0';
if (++poz == DIM)
in.read(buff, DIM), poz = 0;
}
if (sgn == '-')
nr *= -1;
}
void addedge(int x, int y, int cap, int cost)
{
Edge direct = {y, g[y].size(), 0, cap, cost};
Edge inverse = {x, g[x].size(), 0, 0, -cost};
g[x].push_back(direct);
g[y].push_back(inverse);
}
void bellmanford()
{
queue <int> q;
fill(dist + 1, dist + n + 1, INT_MAX);
dist[src] = 0;
q.push(src);
while(!q.empty())
{
int from = q.front();
vis[from] = 0;
q.pop();
for(int i = 0; i < g[from].size(); i++)
{
Edge &e = g[from][i];
if(e.flow < e.cap)
{
int to = e.to;
int newdist = dist[from] + e.cost;
if(newdist < dist[to])
{
dist[to] = newdist;
if(vis[to] == 0)
{
q.push(to);
vis[to] = 1;
}
}
}
}
}
}
void dijkstra()
{
priority_queue<Node, vector<Node>, greater<Node> > pq; //in mod corect
distdij[src] = 0;
pq.push({src, distdij[src]});
vis = 0; //ai inteles de ce pot sa fac asta? Pentru ca e bitset
pushflow[src] = INT_MAX;
while(!pq.empty())
{
int from = pq.top().node;
pq.pop();
if(vis[from] == 0)
{
vis[from] = 1;
for(int i = 0; i < g[from].size(); i++)
{
Edge &e = g[from][i];
if(vis[e.to] == 0)
{
int to = e.to;
if(e.flow < e.cap)
{
int newdistdij = distdij[from] + e.cost + dist[from] - dist[to];
if(newdistdij < distdij[to])
{
distdij[to] = newdistdij;
prevnode[to] = from;
prevedge[to] = i;
pushflow[to] = min(pushflow[from], e.cap - e.flow);
pq.push({to, distdij[to]});
}
}
}
}
}
}
}
void mincostflow(int &flow, int &flowcost)
{
bellmanford();
//cout << "BF\n";
flow = flowcost = 0;
while(distdij[dest] < INT_MAX)
{
fill(distdij + 1, distdij + n + 1, INT_MAX);
dijkstra();
//cout << "DJ\n";
if(distdij[dest] < INT_MAX)
{
//new level graph
for(int i = 1; i <= n; i++)
{
dist[i] += distdij[i];
}
//blocking flow
int deltaflow = pushflow[dest];
flow += deltaflow;
for(int to = dest; to != src; to = prevnode[to])
{
Edge &e = g[prevnode[to]][prevedge[to]];
e.flow += deltaflow;
g[to][e.rev].flow -= deltaflow;
flowcost += deltaflow * e.cost;
//cout << deltaflow << ' ' << e.cost << ' ' << flowcost << '\n';
}
}
}
}
int main()
{
//in >> n >> m >> src >> dest;
read(n);
read(m);
read(src);
read(dest);
//cout << dest << '\n';
for(int i = 1; i <= m; i++)
{
int x, y, cost, cap;
//in >> x >> y >> cap >> cost;
read(x);
read(y);
read(cap);
read(cost);
addedge(x, y, cap, cost);
//cout << x << ' ' << y << ' ' << cap << ' ' << cost << '\n';
}
int flow, flowcost;
mincostflow(flow, flowcost);
out << flowcost << '\n';
in.close();
out.close();
return 0;
}