P1231 教辅的组成 (最大流)

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<int> 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;
}
发布了130 篇原创文章 · 获赞 80 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/KXL5180/article/details/100776941