P1010
本来该使用 Hopcroft 算法的,最终写了 Dinic,Hopcroft 算法有时间再来补吧
#include <bits/stdc++.h>
using i64 = long long;
const int N = 20010, M = (1000010 + N) << 1;
const i64 INF = 0x3f3f3f3f3f3f3f3f;
int T;
int n, m, s, t;
int head[N], to[M], cap[M], nxt[M], idx = 0;
int dep[N], cur[N];
void add(int u, int v, int c)
{
to[idx] = v;
cap[idx] = c;
nxt[idx] = head[u];
head[u] = idx; ++ idx; return;
}
void biadd(int u, int v, int c)
{
add(u, v, c), add(v, u, 0);
return;
}
std::queue<int> q;
bool bfsearch(void)
{
q = std::queue<int>();
for (int i = 1; i <= n + m + 2; ++ i) {
dep[i] = -1;
}
dep[s] = 0, cur[s] = head[s], q.push(s);
while (!q.empty())
{
int fro = q.front(); q.pop();
for (int i = head[fro]; i != -1; i = nxt[i])
{
int e = to[i];
if (dep[e] == -1 && cap[i])
{
cur[e] = head[e];
dep[e] = dep[fro] + 1;
if (e == t) return true;
q.push(e);
}
}
}
return false;
}
i64 extraRoad(int u, i64 lim)
{
if (u == t) return lim;
i64 flow = 0;
for (int i = cur[u]; i != -1 && flow < lim; i = nxt[i])
{
cur[u] = i; int e = to[i];
if (dep[e] == dep[u] + 1 && cap[i])
{
int del = extraRoad(e, std::min(1ll * cap[i], lim - flow));
if (!del) dep[e] = -1;
flow += del, cap[i] -= del, cap[i xor 1] += del;
}
}
return flow;
}
i64 Dinic(void)
{
i64 res = 0, flow;
while (bfsearch())
while (flow = extraRoad(s, INF))
res += flow;
return res;
}
int main(void)
{
scanf("%d", &T);
while (T --) {
int e, inpu, inpv;
scanf("%d%d%d", &n, &m, &e);
for (int i = 1; i <= n + m + 2; ++ i) {
head[i] = -1;
}
idx = 0;
s = n + m + 1, t = n + m + 2;
for (int i = 1; i <= e; ++ i) {
scanf("%d%d", &inpu, &inpv);
biadd(inpu, n + inpv, 1);
}
for (int i = 1; i <= n; ++ i) {
biadd(s, i, 1);
}
for (int i = n + 1; i <= n + m; ++ i) {
biadd(i, t, 1);
}
printf("%lld\n", Dinic());
}
return 0;
}