二分图匹配。
使用最大流求解。
博客中终于有网络流分类了…
建反向边,开两倍空间。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int maxn = 1e5 + 15;
int n, m;
struct edge {
int to, next, val;
} e[maxn];
int head[maxn], cur[maxn], tot;
void add(int u, int v, int w) {
++tot;
e[tot].to = v;
e[tot].val = w;
e[tot].next = head[u];
head[u] = tot;
}
int S, T, dep[maxn];
bool bfs(int st) {
queue<int> q;
memset(dep, 0, sizeof(int) * (m + n + 10));
q.push(st);
dep[st] = 1;
while (!q.empty()) {
int tmp = q.front();
q.pop();
for (int p = head[tmp]; p && !dep[T]; p = e[p].next) {
int v = e[p].to, w = e[p].val;
if (dep[v] || !w) {
continue;
}
dep[v] = dep[tmp] + 1;
q.push(v);
}
}
return dep[T];
}
int dfs(int x, int flow) {
if (x == T || !flow) {
return flow;
}
int rest = flow;
for (int &p = cur[x]; p && rest; p = e[p].next) {
int v = e[p].to, w = e[p].val;
if (dep[v] != dep[x] + 1 || !w) {
continue;
}
int res = dfs(v, min(rest, w));
if (!res) {
dep[v] = 0;
}
e[p].val -= res;
e[p ^ 1].val += res;
rest -= res;
}
return flow - rest;
}
int dinic() {
int maxFlow = 0;
while (bfs(S)) {
for (int i = 0; i <= n + m + 5; ++i) {
cur[i] = head[i];
}
int flow;
while (flow = dfs(S, INT_MAX)) {
maxFlow += flow;
}
}
return maxFlow;
}
int main() {
scanf("%d%d", &m, &n);
S = 0, T = m + n + 5, tot = 1;
int u, v;
while (~scanf("%d%d", &u, &v) && u != -1) {
add(u, v, 1);
add(v, u, 0);
}
for (int i = 1; i <= m; ++i) {
add(S, i, 1);
add(i, S, 0);
}
for (int i = m + 1; i <= m + n; ++i) {
add(i, T, 1);
add(T, i, 0);
}
printf("%d\n", dinic());
for (int i = 2; i <= tot; i += 2) {
if (!e[i].val && e[i].to != S && e[i].to != T && e[i ^ 1].to != S && e[i ^ 1].to != T) {
printf("%d %d\n", e[i ^ 1].to, e[i].to);
}
}
return 0;
}