Pagini recente » Cod sursa (job #2199787) | Cod sursa (job #1584362) | Cod sursa (job #2650172) | Cod sursa (job #801008) | Cod sursa (job #3241686)
#include <bits/stdc++.h>
using namespace std;
struct AugmentedPath {
bool hasPath;
vector<pair<int, int>> path;
AugmentedPath(bool _hasPath, const vector<pair<int, int>>& _path)
: hasPath(_hasPath)
, path(_path) { }
operator bool() const {
return hasPath;
}
};
class EdmondsKarp { // T = O(n * m) aici T = O(n * m^2) in general
public:
void solve() {
read_input();
print_output(get_result());
}
private:
int n, m, e;
vector<vector<int>> adj;
vector<vector<int>> cap;
vector<pair<int, int>> cuplaj;
void read_input() {
ifstream fin("cuplaj.in");
fin >> n >> m >> e;
cap.resize(n + m + 2, vector<int>(n + m + 2, 0));
adj.resize(n + m + 2);
for (int i = 0, u, v; i < e; i++) {
fin >> u >> v;
v += n;
adj[u].push_back(v);
adj[v].push_back(u);
cap[u][v] = 1;
}
for (int i = 1; i <= n; ++i) {
adj[0].push_back(i); // Sursa este nodul 0
adj[i].push_back(0);
cap[0][i] = 1;
}
for (int i = n + 1; i <= n + m; ++i) {
adj[i].push_back(n + m + 1); // Destinația este nodul n + m + 1
adj[n + m + 1].push_back(i);
cap[i][n + m + 1] = 1;
}
fin.close();
}
int get_result() {
return get_maxflow(n + m + 2, 0, n + m + 1);
}
int get_maxflow(int nodes, int source, int sink) {
int total_flow = 0;
vector<vector<int>> flow(nodes, vector<int>(nodes, 0));
while (auto res = bfs(nodes, source, sink, flow)) {
auto& [_, path] = res;
int minFluxPath = INT32_MAX;
for (auto& [u, v] : path) {
minFluxPath = min(minFluxPath, cap[u][v] - flow[u][v]);
}
total_flow += minFluxPath;
for (auto& [u, v] : path) {
flow[u][v] += minFluxPath;
flow[v][u] -= minFluxPath;
}
}
for (int i = 1; i <= n; ++i) {
for (int j = n + 1; j <= m + n; ++j) {
if (flow[i][j] == 1) {
cuplaj.push_back({i, j - n});
}
}
}
return total_flow;
}
AugmentedPath bfs(int nodes, int source, int sink, vector<vector<int>>& flow) {
vector<int> p(nodes, -1);
queue<int> q;
q.push(source);
p[source] = 0;
while (!q.empty()) {
int node = q.front();
q.pop();
for (auto& neigh : adj[node]) {
if (p[neigh] == -1 && flow[node][neigh] < cap[node][neigh]) {
p[neigh] = node;
q.push(neigh);
}
}
}
if (p[sink] == -1) {
return {false, {}};
}
vector<pair<int, int>> path;
int node = sink;
do {
path.push_back({p[node], node});
node = p[node];
} while (node);
reverse(path.begin(), path.end());
return {true, path};
}
void print_output(int result) {
ofstream fout("cuplaj.out");
fout.tie(0);
fout << result << "\n";
for (const auto& edge : cuplaj) {
fout << edge.first << " " << edge.second << "\n";
}
fout.close();
}
};
class HopcroftKarp { // T = O(sqrt(n) * m)
public:
void solve() {
read_input();
print_output(get_result());
}
private:
int n, m, e;
vector<vector<int>> adj;
vector<int> pairU, pairV, dist;
void read_input() {
ifstream fin("cuplaj.in");
fin.tie(0);
fin >> n >> m >> e;
adj.resize(n + 1);
pairU.assign(n + 1, 0);
pairV.assign(m + 1, 0);
dist.assign(n + 1, 0);
for (int i = 0, u, v; i < e; i++) {
fin >> u >> v;
adj[u].push_back(v);
}
fin.close();
}
bool bfs() {
queue<int> q;
for (int u = 1; u <= n; ++u) {
if (pairU[u] == 0) {
dist[u] = 0;
q.push(u);
} else {
dist[u] = INT_MAX;
}
}
dist[0] = INT_MAX;
while (!q.empty()) {
int u = q.front();
q.pop();
if (dist[u] < dist[0]) {
for (int v : adj[u]) {
if (dist[pairV[v]] == INT_MAX) {
dist[pairV[v]] = dist[u] + 1;
q.push(pairV[v]);
}
}
}
}
return dist[0] != INT_MAX;
}
bool dfs(int u) {
if (u != 0) {
for (int v : adj[u]) {
if (dist[pairV[v]] == dist[u] + 1) {
if (dfs(pairV[v])) {
pairV[v] = u;
pairU[u] = v;
return true;
}
}
}
dist[u] = INT_MAX;
return false;
}
return true;
}
int get_result() {
int matching = 0;
while (bfs()) {
for (int u = 1; u <= n; ++u) {
if (pairU[u] == 0 && dfs(u)) {
matching++;
}
}
}
return matching;
}
void print_output(int result) {
ofstream fout("cuplaj.out");
fout.tie(0);
fout << result << "\n";
for (int u = 1; u <= n; ++u) {
if (pairU[u] != 0) {
fout << u << " " << pairU[u] << "\n";
}
}
fout.close();
}
};
int main() {
ios::sync_with_stdio(false);
//auto* task = new (nothrow) EdmondsKarp();
auto* task = new (nothrow) HopcroftKarp();
if (!task) {
cerr << "new failed\n";
return -1;
}
task->solve();
delete task;
return 0;
}