https://www.luogu.org/problem/P1231
题意:给出书,答案和练习册,以及每本书可以匹配的答案和练习册,问最大有多少匹配。
做法:很简单,应该能想到是最大流,但不过建图也很简单,源点-》答案-》书(拆点)-》练习册-》汇点。
但不过每一本书只能用一次,必须要拆点,相当于限流。跑一个最大流就可以了。
#include "bits/stdc++.h"
using namespace std;
inline int read() {
int x = 0;
bool f = 1;
char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') f = 0;
for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0';
if (f) return x;
return 0 - x;
}
const int inf = 0x3f3f3f3f;
const int maxn = 100000 + 10;
int head[maxn], dis[maxn], cnt, cur[maxn];
struct node {
int val, v, nxt;
} e[maxn << 1];
void init() {
cnt = 0;
memset(head, -1, sizeof(head));
}
void add_edge(int u, int v, int val) {
e[cnt].v = v;
e[cnt].val = val;
e[cnt].nxt = head[u];
head[u] = cnt++;
}
int bfs(int s, int t) {
queue qu;
memset(dis, -1, sizeof(dis));
dis[s] = 0;
qu.push(s);
while (!qu.empty()) {
int x = qu.front();
qu.pop();
for (int i = head[x]; i != -1; i = e[i].nxt) {
int now = e[i].v;
if (dis[now] == -1 && e[i].val != 0) {
dis[now] = dis[x] + 1;
qu.push(now);
}
}
}
return dis[t] != -1;
}
int dfs(int x, int t, int maxflow) {
if (x == t) return maxflow;
int ans = 0;
for (int i = head[x]; i != -1; i = e[i].nxt) {
int now = e[i].v;
if (dis[now] != dis[x] + 1 || e[i].val == 0 || ans >= maxflow)
continue;
int f = dfs(now, t, min(e[i].val, maxflow - ans));
e[i].val -= f;
e[i ^ 1].val += f;
ans += f;
///if (!f) dis[now] = -1;
}
return ans;
}
int Dinic(int s, int t) {
int ans = 0;
while (bfs(s, t)) {
///memcpy(cur, head, sizeof(head));
ans += dfs(s, t, inf);
}
return ans;
}
int main() {
init();
int n1, n2, n3, m1, m2, ss, tt, u, v;
n1 = read();
n2 = read();
n3 = read();
ss = 0;
for (int i = 1; i <= n2; i++) {
add_edge(ss, i, 1);
add_edge(i, ss, 0);
}
m1 = read();
for (int i = 1; i <= m1; i++) {
u = read(), v = read();
add_edge(v, u + n2, 1);
add_edge(u + n2, v, 0);
}
for (int i = 1; i <= n1; i++) {
add_edge(i + n2, i + n1 + n2, 1);
add_edge(i + n1 + n2, i + n2, 0);
}
m2 = read();
for (int i = 1; i <= m2; i++) {
u = read(), v = read();
add_edge(n1 + n2 + u, n1 + n2 + n1 + v, 1);
add_edge(n1 + n1 + n2 + v, n1 + n2 + u, 0);
}
tt = n1 + n2 + n1 + n3 + 1;
for (int i = 1; i <= n3; i++) {
add_edge(n1 + n2 + n1 + i, tt, 1);
add_edge(tt, n1 + n2 + n1 + i, 0);
}
cout << Dinic(ss, tt) << endl;
return 0;
}