Cod sursa(job #2648139)

Utilizator MarcGrecMarc Grec MarcGrec Data 8 septembrie 2020 21:30:09
Problema Flux maxim Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.05 kb
#define MAX_N 1000
#define MAX_M 5000
#define INF 0x3f3f3f3f

#include <fstream>
#include <vector>
#include <queue>
#include <list>
#include <memory>
using namespace std;

ifstream fin("maxflow.in");
ofstream fout("maxflow.out");

struct A
{
	A(int _node, int _capacity, int _flow) : node(_node), capacity(_capacity), flow(_flow)
	{
	}
	
	int node, capacity, flow;
	A* inverse = nullptr;
};

using UPA = unique_ptr<A>;

int n, m, s, d, maxFlow, L[MAX_N + 1];
vector<UPA> G[MAX_N + 1];

void Read();
bool Bfs();
void Augment(int node);

int main()
{
	Read();
	
	while (Bfs())
	{
		Augment(s);
	}
	
	fout << maxFlow;
	
	fin.close();
	fout.close();
	return 0;
}

void Read()
{	
	fin >> n >> m;
	
	// Setting the source and destination
	s = 1;
	d = n;
	
	for (int i = 0; i < m; ++i)
	{
		int x, y, c;
		
		fin >> x >> y >> c;
		
		// Edge from x to y
		UPA xy(new A(y, c, 0));
		
		// Edge from y to x (back edge)
		UPA yx(new A(x, 0, 0));
		
		xy->inverse = yx.get();
		
		yx->inverse = xy.get();
		
		G[x].emplace_back(move(xy));
		
		G[y].emplace_back(move(yx));
	}
}

bool Bfs()
{	
	for (int i = 1; i <= n; ++i)
	{
		L[i] = 0;
	}
	
	queue<int> Q;
	Q.push(s);
	L[s] = 1;
	
	while (!Q.empty())
	{
		int node = Q.front();
		Q.pop();
		
		for (const auto& adjNode : G[node])
		{
			if ((L[adjNode->node] == 0) && (adjNode->capacity > adjNode->flow))
			{
				L[adjNode->node] = L[node] + 1;
				Q.push(adjNode->node);
			}
		}
	}
	
	return L[d] != 0;
}

list<A*> path;
void Augment(int node)
{
	if (node == d)
	{
		int mi = INF;
		
		for (A* ptrAdjNode : path)
		{
			mi = min(mi, ptrAdjNode->capacity - ptrAdjNode->flow);
		}
		
		for (A* ptrAdjNode : path)
		{
			ptrAdjNode->flow          += mi;
			ptrAdjNode->inverse->flow -= mi;
		}
		
		maxFlow += mi;
	}
	else
	{	
		for (const auto& adjNode : G[node])
		{
			if (L[adjNode->node] == (L[node] + 1))
			{
				path.push_back(adjNode.get());
				Augment(adjNode->node);
				path.pop_back();
			}
		}
	}
}