zoukankan      html  css  js  c++  java
  • 【网络流24题】 7. 试题库问题 题解

    题目链接(洛谷 P2763)

    题意

    假设一个试题库中有(n)道试题。每道试题都标明了所属类别。同一道题可能有多个类别属性。现要从题库中抽取(m)道题组成试卷。并要求试卷包含指定类型的试题。对于给定的组卷要求,计算满足要求的组卷方案。

    思路

    本题的思路比较显然,从源点向所有种类连接一条容量为该种类题目数量的边,从每一个种类向该种类的每一道题连一条容量为(1)的边,最后从每一道题向汇点连一条容量为(1)的边,跑最大流即可。

    代码

    /**
     * luogu P2763 https://www.luogu.com.cn/problem/P2763
     * Dinic
     **/
    
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <queue>
    
    using namespace std;
    const int maxn = 2000;
    const int maxm = 2e5 + 5;
    const int S = 0;
    const int T = maxn - 1;
    const int INF = 0x3f3f3f3f;
    
    struct Edge {
        int to, nxt, val;
    }e[maxm];
    
    int head[maxn], numedge, n, m, sum, depth[maxn];
    
    inline void _ADD(int from, int to, int val) {
        e[numedge].to = to;
        e[numedge].val = val;
        e[numedge].nxt = head[from];
        head[from] = numedge;
        numedge++;
    }
    
    inline void AddEdge(int from, int to, int val) {
        _ADD(from, to, val);
        _ADD(to, from, 0);
    }
    
    inline bool bfs() {
        memset(depth, 0, sizeof(depth));
        depth[S] = 1;
        queue<int> q;
        q.push(S);
        while (!q.empty()) {
            int u = q.front();
            q.pop();
            for (int i = head[u]; ~i; i = e[i].nxt) {
                int to = e[i].to;
                if (!depth[to] && e[i].val > 0) {
                    depth[to] = depth[u] + 1;
                    q.push(to);
                }
            }
        }
        return depth[T];
    }
    
    inline int dfs(int u, int flow) {
        if (u == T || !flow) return flow;
        int res = 0;
        for (int i = head[u]; ~i; i = e[i].nxt) {
            int to = e[i].to;
            if (depth[to] > depth[u] && e[i].val > 0) {
                int di = dfs(to, min(flow, e[i].val));
                if (di > 0) {
                    flow -= di;
                    e[i].val -= di;
                    e[i ^ 1].val += di;
                    res += di;
                }
            }
        }
        if (!res) depth[u] = 0;
        return res;
    }
    
    int Dinic() {
        int res = 0;
        while (bfs())
            res += dfs(S, INF);
        return res;
    }
    
    int main() {
        memset(head, -1, sizeof(head));
        scanf("%d%d", &n, &m);
        for (int i = 1; i <= n; i++) {
            int x;
            scanf("%d", &x);
            sum += x;
            AddEdge(S, i, x);
        }
        for (int i = 1; i <= m; i++) {
            int x, y;
            scanf("%d", &x);
            for (int j = 1; j <= x; j++) {
                scanf("%d", &y);
                AddEdge(y, i + n, 1);
            }
            AddEdge(i + n, T, 1);
        }
    
        // for (int i = 0; i <= n + m; i++) {
        //     printf("%d:
    ", i);
        //     for (int j = head[i]; ~j; j = e[j].nxt) {
        //         int to = e[j].to;
        //         if (e[j].val)
        //             printf("%d %d
    ", to, e[j].val);
        //     }
        //     // putchar('
    ');
        // }
    
    
        int res = Dinic();
        if (res < sum) {
            printf("No Solution!
    ");
        }
        else {
            for (int i = 1; i <= n; i++) {
                printf("%d:", i);
                for (int j = head[i]; ~j; j = e[j].nxt) {
                    int to = e[j].to;
                    if (to > n && !e[j].val) {
                        printf(" %d", to - n);
                    }
                }
                putchar('
    ');
            }
        }
        return 0;
    }
    
  • 相关阅读:
    自考新教材-p209
    自考新教材-p205
    自考新教材-p200
    自考新教材-p197
    Java IO (5)
    Java IO (1)
    Java IO (2)
    Java IO (3)
    通过源码学Java基础:InputStream、OutputStream、FileInputStream和FileOutputStream
    Spring入门(1)-第一个Spring项目
  • 原文地址:https://www.cnblogs.com/icysky/p/13623266.html
Copyright © 2011-2022 走看看