Pagini recente » Diferente pentru preoni-2007/runda-3/solutii intre reviziile 26 si 27 | Poze finala preONI 2006 | Monitorul de evaluare | Autentificare | Cod sursa (job #2648049)
#define MAX_N 1000
#define INF 0x3f3f3f3f
#include <fstream>
#include <vector>
#include <queue>
#include <bitset>
#include <algorithm>
using namespace std;
ifstream fin("maxflow.in");
ofstream fout("maxflow.out");
struct edge
{
int u, v, flow, capacity;
edge* reverse;
};
struct edgestacknode
{
edgestacknode(edge* _e) :
e(_e)
{
}
edge* e;
edgestacknode* prev = nullptr;
};
struct edgestack
{
~edgestack()
{
while (!Empty())
{
Pop();
}
}
edgestacknode* top = nullptr;
void Push(edgestacknode* node)
{
edgestacknode* prev = top;
top = node;
top->prev = prev;
}
void Pop()
{
edgestacknode* prev = top->prev;
delete top;
top = prev;
}
bool Empty() const
{
return top == nullptr;
}
};
int n, m, maxFlow, L[MAX_N + 1];
vector<edge*> G[MAX_N + 1];
bitset<MAX_N + 1> E;
void Read();
bool Bfs();
bool Augment(int node);
int main()
{
Read();
while (true)
{
E.set();
if (!Bfs())
{
break;
}
Augment(1);
}
// Cleanup.
for (int i = 1; i <= n; ++i)
{
for (edge* ptr : G[i])
{
delete ptr;
}
G[i].clear();
}
fout << maxFlow;
fin.close();
fout.close();
return 0;
}
void Read()
{
fin >> n >> m;
for (int i = 0, x, y, c; i < m; ++i)
{
fin >> x >> y >> c;
edge* a = new edge;
a->u = x;
a->v = y;
a->flow = 0;
a->capacity = c;
edge* b = new edge;
b->u = y;
b->v = x;
b->flow = 0;
b->capacity = 0;
a->reverse = b;
b->reverse = a;
G[x].push_back(a);
G[y].push_back(b);
}
}
bool Bfs()
{
for (int i = 1; i <= n; ++i)
{
L[i] = INF;
}
queue<int> Q;
Q.push(1);
L[1] = 1;
while (!Q.empty())
{
int curr = Q.front();
Q.pop();
for (edge* e : G[curr])
{
if (E[e->v] && (L[e->v] > (L[curr] + 1)) && (e->capacity > e->flow))
{
L[e->v] = L[curr] + 1;
Q.push(e->v);
}
}
}
return (L[n] != INF);
}
edgestack path;
bool Augment(int node)
{
if (node == n)
{
int mi = INF;
for (edgestacknode* it = path.top; it != nullptr; it = it->prev)
{
mi = min(mi, it->e->capacity - it->e->flow);
}
for (edgestacknode* it = path.top; it != nullptr; it = it->prev)
{
it->e->flow += mi;
it->e->reverse->flow -= mi;
}
maxFlow += mi;
return true;
}
bool res = false;
for (edge* e : G[node])
{
if (E[e->v] && (L[e->v] == (L[node] + 1)) && (e->capacity > e->flow))
{
path.Push(new edgestacknode(e));
bool res_neigh = Augment(e->v);
path.Pop();
if (!res_neigh)
{
E[e->v] = false;
}
else
{
res = true;
}
}
}
return res;
}