Pagini recente » Cod sursa (job #290332) | Cod sursa (job #669055) | Cod sursa (job #2525998) | Cod sursa (job #1978649) | Cod sursa (job #3042198)
#include <bits/stdc++.h>
#define int long long
using namespace std;
//#define LOCAL
#ifdef LOCAL
ifstream in("in.in");
ofstream out("out.out");
#else
ifstream in("cuplaj.in");
ofstream out("cuplaj.out");
#endif
const int inf = (1LL << 61);
namespace MaxFlow {
struct Edge {
int to,rev,cap,flow;
};
vector<Edge> edges;
vector<vector<int>> g;
vector<int> parent,dis,parentEdge;
void init(int n) {
g.resize(n + 1);
dis.resize(n + 1);
parent.resize(n +1);
parentEdge.resize(n+1);
}
void add_edge(int u, int v, int cap) {
//cout << "add edge " << u << " " << v << "\n";
g[u].push_back(edges.size());
edges.push_back(Edge{v,(int)edges.size(),cap,0});
g[v].push_back(edges.size());
edges.push_back(Edge{u,(int)edges.size() - 1, 0, 0});
}
int dif(const Edge &v) {
return v.cap - v.flow;
}
bool bfs(int s, int t) {
fill(dis.begin(),dis.end(),inf);
fill(parent.begin(),parent.end(),-1);
queue<int> q;
dis[s] = 0;
q.push(s);
while(!q.empty()) {
int node = q.front();
q.pop();
for (auto e : g[node]) {
int to = edges[e].to;
if (dis[node] + 1 < dis[to] && dif(edges[e])) {
dis[to] = dis[node] + 1;
parent[to] = node;
parentEdge[to] = e;///the edge that got us here
q.push(to);
}
}
}
return (parent[t] != -1);
}
int get_flow(int s, int t) {
int total_flow = 0;
while(bfs(s,t)) {
int node = t,bottle_neck = inf;
while(parent[node] != -1) {
int from = parent[node];
bottle_neck = min(bottle_neck, dif(edges[parentEdge[node]]));
node = from;
}
node = t;
while(parent[node] != -1) {
int from = parent[node];
edges[parentEdge[node]].flow += bottle_neck;
edges[parentEdge[node]^1].flow -= bottle_neck;
node = from;
}
total_flow += bottle_neck;
}
return total_flow;
}
}
int n,m,e;
int32_t main() {
in >> n >> m >> e;
MaxFlow::init(n + m + 1);
for (int i = 1; i <= n; i++) {
MaxFlow::add_edge(0,i,1);
}
for (int i = 1; i <=m; i++) {
MaxFlow::add_edge(i + n, n + m + 1,1);
}
vector<pair<int,int>> edges;
edges.reserve(e);
for (int i = 1; i <= e; i++) {
int u,v;
in >> u >> v;
edges.push_back({u,v});
}
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
shuffle(edges.begin(),edges.end(),rng);
for (int i = 0; i < e; i++) {
int u,v;
u = edges[i].first;
v = edges[i].second;
MaxFlow::add_edge(u,v + n,1);
}
out << MaxFlow::get_flow(0,n+m+1) << "\n";
for (int i = 1; i <= n; i++) {
for (auto k : MaxFlow::g[i]) {
if (MaxFlow::edges[k].flow > 0) {
out << i << " " << -n + MaxFlow::edges[k].to << "\n";
}
}
}
}