Pagini recente » Cod sursa (job #968332) | Cod sursa (job #549342) | Cod sursa (job #2868825) | Cod sursa (job #2789296) | Cod sursa (job #2698613)
#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
typedef signed long long ll;
typedef unsigned int uint;
typedef unsigned short ushort;
typedef unsigned char uchar;
template <typename T>
void printarray(T v[], uint n) {for(uint i = 0; i < n; i ++){cout << v[i] << " ";}cout << endl;}
template <typename T>
void printvector(vector<T> v){for (uint i = 0; i < v.size(); i ++){cout << v[i] << " ";}cout << endl;}
#define dbg(x) cout << #x " = " << x << " | ";
#define dbgnl(x) cout << #x " = " << x << endl;
const uint nmax = 10005 * 2;
const int INF = 2e9;
const char capacity = 1;
struct edge_t {
int node;
char flow, capacity;
list<edge_t>::iterator opposite;
};
typedef list<edge_t>::iterator edge_iter;
list<edge_t> G[nmax];
edge_iter parent_edge[nmax];
int maxflow = 0;
int n, m, e;
int source, dest;
bitset<nmax> visited;
#define A_NODE(i) (i)
#define B_NODE(i) (i+n)
void read() {
cin >> n >> m >> e;
source = 0;
dest = n + m + 1;
for (int i = 0; i < e; i++) {
int x, y;
cin >> x >> y;
G[A_NODE(x)].push_back({.node = B_NODE(y), .flow = 0, .capacity = 1});
G[B_NODE(y)].push_back({.node = A_NODE(x), .flow = 0, .capacity = 0});
// Link the edge going in the opposite direction
G[A_NODE(x)].back().opposite = next(G[B_NODE(y)].end(), -1);
G[B_NODE(y)].back().opposite = next(G[A_NODE(x)].end(), -1);
}
for (int i = 1; i <= n; i++) {
G[source].push_back({.node = A_NODE(i), .flow = 0, .capacity = 1});
G[A_NODE(i)].push_back({.node = source, .flow = 0, .capacity = 0});
G[source].back().opposite = next(G[A_NODE(i)].end(), -1);
G[A_NODE(i)].back().opposite = next(G[source].end(), -1);
}
for (int i = 1; i <= m; i++) {
G[B_NODE(i)].push_back({.node = dest, .flow = 0, .capacity = 1});
G[dest].push_back({.node = B_NODE(i), .flow = 0, .capacity = 0});
G[B_NODE(i)].back().opposite = next(G[dest].end(), -1);
G[dest].back().opposite = next(G[B_NODE(i)].end(), -1);
}
}
bool bfs() {
queue<int> q;
q.push(source);
visited[source] = true;
while (!q.empty()) {
int node = q.front();
q.pop();
if (node == dest) break;
for (auto edge_it = G[node].begin(); edge_it != G[node].end(); ++edge_it) {
if (!visited[edge_it->node] && edge_it->flow < edge_it->capacity) {
visited[edge_it->node] = true;
q.push(edge_it->node);
parent_edge[edge_it->node] = edge_it;
}
}
}
if (visited[dest] == false) return false;
int cur_node = dest;
char minflow = CHAR_MAX;
while (cur_node != source) {
minflow = min(minflow, (char)(parent_edge[cur_node]->capacity - parent_edge[cur_node]->flow));
cur_node = parent_edge[cur_node]->opposite->node;
}
cur_node = dest;
while (cur_node != source) {
parent_edge[cur_node]->flow += minflow;
parent_edge[cur_node]->opposite->flow -= minflow;
cur_node = parent_edge[cur_node]->opposite->node;
}
maxflow += minflow;
return true;
}
void solve() {
bool retry = true;
while(retry) {
retry = bfs();
visited.reset();
}
}
void write() {
cout << maxflow << "\n";
for (auto edge: G[source]) {
if (edge.flow == edge.capacity) {
for (auto match: G[edge.node]) {
if (match.flow == match.capacity && match.node != source) {
cout << (int)edge.node << " " << (int)(match.node-n) << "\n";
}
}
}
}
}
int main() {
freopen("cuplaj.in", "r", stdin);
freopen("cuplaj.out", "w", stdout);
read();
solve();
write();
return 0;
}