Cod sursa(job #2883151)

Utilizator cristi124349Ilovan Cristian cristi124349 Data 1 aprilie 2022 10:59:22
Problema Flux maxim Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.26 kb
#include<fstream>
#include<vector>
#include<queue>

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

struct Edge
{
	int destination_node,
		flow,
		capacity,
		index_of_reverse_edge;
};

class Graph
{
public:
	Graph(int const& number_of_nodes)
	{
		adj = new std::vector<Edge>[number_of_nodes];

		this->number_of_nodes = number_of_nodes;

		distance = new int[number_of_nodes];
	}

	// Add the edge from i to j with c capacity;
	// Also add the reverse edge with 0 capacity;
	inline void add_edge(int const& i, int const& j, int const& c);
	inline bool bfs(int const& start, int const& finish);
	inline int send_flow(int const& current_node, int const& flow, int const& finish, int placed[]);
	inline int DinicMaxflow(int const& start, int const& finish);

private:
	int number_of_nodes;
	int* distance;
	std::vector<Edge>* adj;
};

inline void Graph::add_edge(int const& i, int const& j, int const& c)
{
	Edge a{ j, 0, c, adj[j].size() };
	Edge b{ i, 0, 0, adj[i].size() };

	adj[i].push_back(a);
	adj[j].push_back(b);
}

inline bool Graph::bfs(int const& start, int const& finish)
{
	for (int index = 0; index < number_of_nodes; ++index)
		distance[index] = -1;

	distance[start] = 0;

	int current_node;
	std::queue<int> Q;
	Q.push(start);

	while (!Q.empty())
	{
		current_node = Q.front(), Q.pop();

		for (auto const& current_edge : adj[current_node])
		{
			if (distance[current_edge.destination_node] < 0 && current_edge.flow < current_edge.capacity)
			{
				distance[current_edge.destination_node] = distance[current_node] + 1;

				Q.push(current_edge.destination_node);
			}
		}
	}

	return distance[finish] < 0 ? false : true;
}

inline int Graph::send_flow(int const& current_node, int const& flow, int const& finish, int placed[])
{
	if (current_node == finish)
		return flow;

	for (; placed[current_node] < adj[current_node].size(); ++placed[current_node])
	{
		Edge& current_edge = adj[current_node][placed[current_node]];

		if (distance[current_edge.destination_node] == distance[current_node] + 1 && current_edge.flow < current_edge.capacity)
		{
			// find minimum flow from start to finish
			int curr_flow = std::min(flow, current_edge.capacity - current_edge.flow);

			int temp_flow = send_flow(current_edge.destination_node, curr_flow, finish, placed);

			// flow is greater than zero
			if (temp_flow > 0)
			{
				// add flow to current edge
				current_edge.flow += temp_flow;

				// subtract flow from reverse edge
				// of current edge
				adj[current_edge.destination_node][current_edge.index_of_reverse_edge].flow -= temp_flow;

				return temp_flow;
			}
		}
	}

	return 0;
}

inline int Graph::DinicMaxflow(int const& start, int const& finish)
{
	if (start == finish)
		return -1;

	int total = 0;

	while (bfs(start, finish))
	{
		int* placed = new int[1LL * number_of_nodes + 1]{ 0 };

		while (int flow = send_flow(start, 2e9, finish, placed))
			total += flow;
	}

	return total;
}

int main()
{
	int n, m, i, j, c;
	fin >> n >> m;
	Graph r(n);
	for (int k = 1; k <= m; ++k)
	{
		fin >> i >> j >> c;
		r.add_edge(i - 1, j - 1, c);
	}
	int R = r.DinicMaxflow(0, n - 1);
	if (R) fout << R;
	else fout << "Apa nu ajunge!";
	return 0;
}