P1231 教辅的组成(拆点)
思路:对课本拆点,限制课本使用次数为1,然后这样连边,课本发出点->练习册,容量为1,答案->课本接收点,容量为1
源点->答案,容量为1,练习册连汇点,容量为1,最终形成源点->答案->课本接受点->课本发出点->练习册->汇点的网络图
然后跑网络流,这样就能得到最大匹配成功数了
AC代码:
int main() { //freopen("test.txt", "r", stdin); scanf("%d%d%d", &n1, &n2, &n3); scanf("%d", &m1); s = n1*2 + n2 + n3 + 1, d = s + 1; for (int i = 1; i <= n1; i++) {//对课本拆点 add(i, i + n1, 1); add(n1 + i, i, 0); } for (int i = 1; i <= m1; i++) {//课本出发点->练习册 int a, b; scanf("%d%d", &a, &b); add(a + n1, b + n1 * 2, 1); add(b + n1 * 2, a + n1, 0); } scanf("%d", &m2); for (int i = 1; i <= m2; i++) {//答案->课本接受点 int a, b; scanf("%d%d", &a, &b); add(b + n1 * 2 + n2, a, 1); add(a, b + n1 * 2 + n2, 0); } for (int i = 1; i <= n3; i++) {//源点->答案 add(s, i+n1*2+n2, 1); add(i+n1*2+n2, s, 0); } for (int i = 1; i <= n2; i++) {//练习册->汇点 add(i + n1*2, d, 1); add(d, i + n1*2, 0); } printf("%lld\n", dinic()); return 0; }