1 条题解

  • 0
    @ 2025-8-24 21:13:51

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar EuphoricStar
    Remember.

    搬运于2025-08-24 21:13:50,当前版本为作者最后更新于2021-07-05 07:06:59,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    思路

    本题可转化为最大流问题。

    设源点为 11,汇点为 nl+nr+2nl + nr + 2,左侧点编号为 22 ~ nl+1nl + 1,右侧点编号为 nl+2nl + 2 ~ nl+nr+1nl + nr + 1

    然后源点向每个左侧点连一条容量为 11 的边,每个右侧点向汇点连一条容量为 11 的边,左侧点和右侧点按照输入的边连一条容量为 11 的边,然后跑一遍 Dinic,此时最大流便是答案。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    
    const int maxn = 1020, maxm = 511000, inf = 0x3f3f3f3f;
    
    int n, nl, nr, m, s, t, head[maxn], len;
    struct edge {
        int from, to, next, cap, flow;
    } edges[maxm];
    
    void add_edge(int u, int v, int c, int f) {
        edges[++len].from = u;
        edges[len].to = v;
        edges[len].next = head[u];
        edges[len].cap = c;
        edges[len].flow = f;
        head[u] = len;
    }
    
    struct Dinic {
        bool vis[maxn];
        int d[maxn], cur[maxn];
    
        void add(int u, int v, int c) {
            add_edge(u, v, c, 0);
            add_edge(v, u, 0, 0);
        }
    
        bool bfs() {
            memset(vis, 0, sizeof(vis));
            queue<int> q;
            d[s] = 0;
            vis[s] = 1;
            q.push(s);
            while (q.size()) {
                int u = q.front();
                q.pop();
                for (int i = head[u]; i; i = edges[i].next) {
                    edge e = edges[i];
                    if (!vis[e.to] && e.cap > e.flow) {
                        vis[e.to] = 1;
                        d[e.to] = d[u] + 1;
                        q.push(e.to);
                    }
                }
            }
            return vis[t];
        }
    
        int dfs(int u, int a) {
            if (u == t || !a) {
                return a;
            }
            int flow = 0, f;
            for (int &i = cur[u]; i; i = edges[i].next) {
                edge &e = edges[i];
                if (d[u] + 1 == d[e.to] && (f = dfs(e.to, min(a, e.cap - e.flow))) > 0) {
                    e.flow += f;
                    edges[i ^ 1].flow -= f;
                    flow += f;
                    a -= f;
                    if (!a) {
                        break;
                    }
                }
            }
            return flow;
        }
    
        int solve() {
            int flow = 0;
            while (bfs()) {
                for (int i = 1; i <= n; ++i) {
                    cur[i] = head[i];
                }
                flow += dfs(s, inf);
            }
            return flow;
        }
    } solver;
    
    int main() {
        scanf("%d%d%d", &nl, &nr, &m);
        s = 1;
        t = n = nl + nr + 2;
        len = 1;
        for (int i = 1; i <= nl; ++i) {
            solver.add(s, i + 1, 1);
        }
        for (int i = 1; i <= nr; ++i) {
            solver.add(i + nl + 1, t, 1);
        }
        while (m--) {
            int u, v;
            scanf("%d%d", &u, &v);
            solver.add(u + 1, v + nl + 1, 1);
        }
        printf("%d", solver.solve());
        return 0;
    }
    
    • 1

    信息

    ID
    6855
    时间
    1000ms
    内存
    512MiB
    难度
    4
    标签
    (无)
    递交数
    0
    已通过
    0
    上传者