拆点建图,跑EK,拆掉牛即可。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <stack>
#define MAX 501
#define INF 0x3f3f3f3f
using namespace std;
int n, f, d;
int gra[MAX][MAX];
int visit[MAX];
int S, E;
int pre[MAX];
stack<int> Q;
bool E_K() {
memset(visit, 0, sizeof(visit));
visit[0] = 1;
pre[0] = -1;
while (!Q.empty()) {
Q.pop();
}
Q.push(S);
while (!Q.empty()) {
int front = Q.top();
Q.pop();
for (size_t i = S; i <= E; i++) {
if (!visit[i] && gra[front][i] > 0) {
Q.push(i);
visit[i] = 1;
pre[i] = front;
}
}
}
return visit[E] == 1;
}
int main() {
while (~scanf("%d%d%d", &n, &f, &d)) {
S = 0;
E = 2 * n + f + d + 1;
memset(gra, 0, sizeof(gra));
int c1, c2, F, D;
for (size_t i = 1; i <= n; i++) {
scanf("%d%d", &c1, &c2);
for (size_t j = 1; j <= c1; j++) {
scanf("%d", &F);
gra[F][f + 2 * i - 1] = 1;
gra[S][F] = 1;
}
for (size_t k = 1; k <= c2; k++) {
scanf("%d", &D);
gra[f + 2 * i][f + 2 * n + D] = 1;
gra[f + 2 * n + D][E] = 1;
}
}
for (int i = 1; i <= 2 * n; i++) {
gra[f + 2 * i - 1][f + 2 * i] = 1;
}
int path_flow = INF;
int max_flow = 0;
while (E_K()) {
for (int v = E; v != S; v = pre[v]) {
int u = pre[v];
path_flow = min(path_flow, gra[u][v]);
}
for (int v = E; v != S; v = pre[v]) {
int u = pre[v];
gra[u][v] -= path_flow;
gra[v][u] += path_flow;
}
max_flow += path_flow;
}
printf("%d\n", max_flow);
}
return 0;
}
网友评论