Pagini recente » Cod sursa (job #1697162) | Cod sursa (job #2551958) | Cod sursa (job #1020778) | Rating Miriam Irimia (Miriamirimia) | Cod sursa (job #2967124)
#include <iostream>
#include <fstream>
#include <list>
#include <vector>
#include <tuple>
#include <queue>
using namespace std;
// Declaring input and output files
ifstream f("cuplaj.in");
ofstream g("cuplaj.out");
int sizeLeft, sizeRight, edges;
int s, t;
vector < bool > inRight;// Initializing a vector to keep track of which nodes are in the right set
vector < pair < int, int >> parent, nodesRight;
vector < vector < pair < int, pair < int, int >>>> adjList;// Initializing a 2D vector to store the adjacency list of the graph
// Function to create an edge between two nodes
void createEdge(int x, int y) {
// Adding edge to adjacency list
adjList[x].push_back({y, {1,adjList[y].size()}});
adjList[y].push_back({x, {0,adjList[x].size() - 1}});
// If the node y is the sink, adding it to the nodesRight vector
if (y == t) {
nodesRight.emplace_back(x, adjList[x].size() - 1);
}
}
// Breadth-first search function to find augmenting paths
bool bf() {
vector < bool > visited(t+1);
queue < int > q;
q.push(s);
visited[s] = true;
parent[s] = {-1, -1};
// While queue is not empty
while (!q.empty()) {
int firstInQueue = q.front();
q.pop();
if (firstInQueue == t) {
continue;
}
int i = 0;
// Iterating through all adjacent nodes
for (auto const& adjNode: adjList[firstInQueue]) {
int c = adjNode.second.first;
int node = adjNode.first;
if (!visited[node] && c) {
parent[node] = {firstInQueue, i};
visited[node] = true;
q.push(node);
}
++i;
}
}
// Returning whether sink is visited or not
return visited[t];
}
long long int cuplaj() {
long long int maxFlow = 0;
// While there exists an augmenting path
while (bf()) {
for (auto const& adjNode: nodesRight) {
int currentFlow = 1;
parent[t] = adjNode;
int y = t;
// Finding the minimum flow in the augmenting path
while (parent[y].first != -1) {
int u = parent[y].first;
int v = parent[y].second;
currentFlow = min(currentFlow, adjList[u][v].second.first);
y = u;
}
y = t;
// Updating the flow on the edges
while (parent[y].first != -1) {
int u = parent[y].first;
int v = parent[y].second;
int w = adjList[u][v].second.second;
adjList[u][v].second.first -= currentFlow;
adjList[y][w].second.first += currentFlow;
y = u;
}
maxFlow += currentFlow;
}
}
return maxFlow;
}
int main() {
// Reading input data
f >> sizeLeft >> sizeRight >> edges;
// Setting sink node
t = sizeLeft + sizeRight + 1;
inRight.resize(sizeRight + 1);
parent.resize(t + 1);
adjList.resize(t + 1);
// Creating edges from source to all left nodes
for (int i = 1; i <= sizeLeft; ++i) {
createEdge(s, i);
}
// Creating edges between left and right nodes
for (int i = 1; i <= edges; ++i) {
int x, y;
f>> x >> y;
createEdge(x, sizeLeft + y);
inRight[y] = true;
}
// Creating edges from all right nodes that have edges to sink
for (int i = 1; i <= sizeRight; ++i) {
if (inRight[i]) {
createEdge(sizeLeft + i, t);
}
}
// Finding the maximum matching and outputting the result
g << cuplaj() << '\n';
for (int u = 1; u <= sizeLeft; ++u) {
for (auto const &node: adjList[u]) {
int vertex, capacity;
vertex = node.first;
capacity = node.second.first;
if (vertex && capacity == 0 && vertex != t) {
g << u << " " << vertex - sizeLeft << '\n';
}
}
}
}