zoukankan      html  css  js  c++  java
  • P2763 试题库问题 【网络流24题】【最大流】【路径覆盖】

    题目描述

    问题描述:

    假设一个试题库中有 nn 道试题。每道试题都标明了所属类别。同一道题可能有多个类别属性。现要从题库中抽取 mm 道题组成试卷。并要求试卷包含指定类型的试题。试设计一个满足要求的组卷算法。

    编程任务:

    对于给定的组卷要求,计算满足要求的组卷方案。

    输入格式

    第一行有两个正整数 kk 和 nn。kk 表示题库中试题类型总数,nn 表示题库中试题总数。

    第二行有 kk 个正整数,第 ii 个正整数表示要选出的类型 ii 的题数。这 kk 个数相加就是要选出的总题数 mm。

    接下来的 nn 行给出了题库中每个试题的类型信息。每行的第一个正整数 pp 表明该题可以属于 pp 类,接着的 pp 个数是该题所属的类型号。

    输出格式

    输出共 kk 行,第 ii 行输出 i: 后接类型 ii 的题号。
    如果有多个满足要求的方案,只要输出一个方案。
    如果问题无解,则输出No Solution!

    输入输出样例

    输入 #1
    3 15
    3 3 4
    2 1 2
    1 3
    1 3
    1 3
    1 3
    3 1 2 3
    2 2 3
    2 1 3
    1 2
    1 2
    2 1 2
    2 1 3
    2 1 2
    1 1
    3 1 2 3
    输出 #1
    1: 1 6 8
    2: 7 9 10
    3: 2 3 4 5

    思路

      对于这种有限制的分配问题很容易想到用网络流建图解决

      对于这道题,显然可以把试题和类型看做成二部图的两个部分

      因为每道题只可以选一次

      显然这张图的边容量最大为1

      然后对整张图跑最大流

      如果最大流 == 需要的题数

      说明有方案

      如何输出方案

      类似于前面那道飞行员问题

      因为容量为1,只要这条边被利用过,

      悔边的容量一定为1.

      所以只需要枚举所有被用到的类型的悔边即可

    CODE

      1 #include <bits/stdc++.h>
      2 #define dbg(x) cout << #x << "=" << x << endl
      3 #define eps 1e-8
      4 #define pi acos(-1.0)
      5 
      6 using namespace std;
      7 typedef long long LL;
      8 
      9 const int inf = 0x3f3f3f3f;
     10 
     11 template<class T>inline void read(T &res)
     12 {
     13     char c;T flag=1;
     14     while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;res=c-'0';
     15     while((c=getchar())>='0'&&c<='9')res=res*10+c-'0';res*=flag;
     16 }
     17 
     18 namespace _buff {
     19     const size_t BUFF = 1 << 19;
     20     char ibuf[BUFF], *ib = ibuf, *ie = ibuf;
     21     char getc() {
     22         if (ib == ie) {
     23             ib = ibuf;
     24             ie = ibuf + fread(ibuf, 1, BUFF, stdin);
     25         }
     26         return ib == ie ? -1 : *ib++;
     27     }
     28 }
     29 
     30 int qread() {
     31     using namespace _buff;
     32     int ret = 0;
     33     bool pos = true;
     34     char c = getc();
     35     for (; (c < '0' || c > '9') && c != '-'; c = getc()) {
     36         assert(~c);
     37     }
     38     if (c == '-') {
     39         pos = false;
     40         c = getc();
     41     }
     42     for (; c >= '0' && c <= '9'; c = getc()) {
     43         ret = (ret << 3) + (ret << 1) + (c ^ 48);
     44     }
     45     return pos ? ret : -ret;
     46 }
     47 
     48 const int maxn = 200007;
     49 
     50 int n, m;
     51 int s, t;
     52 
     53 struct edge{
     54     int from,to;
     55     LL cap,flow;
     56 };
     57 
     58 map<int, int> vis;
     59 
     60 struct DINIC {
     61     int head[maxn << 1], nxt[maxn << 1], edge[maxn << 1], cnt;
     62     int cap[maxn << 1], depth[maxn << 1];
     63 
     64     void init() {
     65         cnt = 1;
     66         memset(head, 0, sizeof(head));
     67     }
     68 
     69     void BuildGraph(int u, int v, int w) {
     70         ++cnt;
     71         edge[cnt] = v;
     72         nxt[cnt] = head[u];
     73         cap[cnt] = w;
     74         head[u] = cnt;
     75 
     76         ++cnt;
     77         edge[cnt] = u;
     78         nxt[cnt] = head[v];
     79         cap[cnt] = 0;
     80         head[v] = cnt;
     81     }
     82 
     83     queue<int> q;
     84 
     85     bool bfs() {
     86         memset(depth, 0, sizeof(depth));
     87         depth[s] = 1;
     88         q.push(s);
     89         while(!q.empty()) {
     90             int u = q.front();
     91             q.pop();
     92             for ( int i = head[u]; i; i = nxt[i] ) {
     93                 int v = edge[i];
     94                 if(depth[v]) {
     95                     continue;
     96                 }
     97                 if(cap[i]) {
     98                     depth[v] = depth[u] + 1;
     99                     q.push(v);
    100                 }
    101             }
    102         }
    103         return depth[t];
    104     }
    105 
    106     int dfs(int u, int dist) {
    107         if(u == t) {
    108             return dist;
    109         }
    110         int flow = 0;
    111         for ( int i = head[u]; i && dist; i = nxt[i] ) {
    112             if(cap[i] == 0)
    113                 continue;
    114             int v = edge[i];
    115             if(depth[v] != depth[u] + 1) {
    116                 continue;
    117             }
    118             int res = dfs(v, min(cap[i], dist));
    119             cap[i] -= res;
    120             cap[i ^ 1] += res;
    121             //printf("cap[%d]:%d
    ",t, cap[t]);
    122             dist -= res;
    123             flow += res;
    124         }
    125         return flow;
    126     }
    127 
    128     int maxflow() {
    129         int ans = 0;
    130         while(bfs()) {
    131             ans += dfs(s, inf);
    132         }
    133         return ans;
    134     }
    135 } dinic;
    136 
    137 int main()
    138 {
    139     //freopen("data.txt", "r", stdin);
    140     int k;
    141     read(k); read(n);
    142     dinic.init();
    143     s = 0, t = n + k + 1;
    144     int x;
    145     for ( int i = 1; i <= k; ++i ) {
    146         read(x);
    147         m += x;
    148         dinic.BuildGraph(n + i, t, x);
    149     }
    150     for ( int i = 1; i <= n; ++i ) {
    151         dinic.BuildGraph(s, i, 1);
    152         int p;
    153         read(p);
    154         for ( int j = 1; j <= p; ++j ) {
    155             read(x);
    156             dinic.BuildGraph(i, x + n, 1);
    157         }
    158     }
    159     int tot = dinic.maxflow();
    160     //dbg(tot);
    161     if(tot != m) {
    162         puts("No Solution!");
    163     }
    164     else {
    165         for ( int i = 1; i <= k; ++i ) {
    166             int u = n + i;
    167             printf("%d:",i);
    168             for ( int j = dinic.head[u]; j; j = dinic.nxt[j] ) {
    169                 int v = dinic.edge[j];
    170                 if(dinic.cap[j] && v <= n) {
    171                     printf(" %d",v);
    172                 }
    173             }
    174             printf("
    ");
    175         }
    176     }
    177     return 0;
    178 }
    View Code
    #include <bits/stdc++.h>
    #define dbg(x) cout << #x << "=" << x << endl
    #define eps 1e-8
    #define pi acos(-1.0)

    using namespace std;
    typedef long long LL;

    const int inf = 0x3f3f3f3f;

    template<class T>inline void read(&res)
    {
        char c;T flag=1;
        while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;res=c-'0';
        while((c=getchar())>='0'&&c<='9')res=res*10+c-'0';res*=flag;
    }

    namespace _buff {
        const size_t BUFF = 1 << 19;
        char ibuf[BUFF], *ib = ibuf, *ie = ibuf;
        char getc() {
            if (ib == ie) {
                ib = ibuf;
                ie = ibuf + fread(ibuf, 1, BUFF, stdin);
            }
            return ib == ie ? -1 : *ib++;
        }
    }

    int qread() {
        using namespace _buff;
        int ret = 0;
        bool pos = true;
        char c = getc();
        for (; (< '0' || c > '9') && c != '-'; c = getc()) {
            assert(~c);
        }
        if (== '-') {
            pos = false;
            c = getc();
        }
        for (; c >= '0' && c <= '9'; c = getc()) {
            ret = (ret << 3) + (ret << 1) + (^ 48);
        }
        return pos ? ret : -ret;
    }

    const int maxn = 200007;

    int n, m;
    int s, t;

    struct edge{
        int from,to;
        LL cap,flow;
    };

    map<int, int> vis;

    struct DINIC {
        int head[maxn << 1], nxt[maxn << 1], edge[maxn << 1], cnt;
        int cap[maxn << 1], depth[maxn << 1];

        void init() {
            cnt = 1;
            memset(head, 0, sizeof(head));
        }

        void BuildGraph(int u, int v, int w) {
            ++cnt;
            edge[cnt] = v;
            nxt[cnt] = head[u];
            cap[cnt] = w;
            head[u] = cnt;

            ++cnt;
            edge[cnt] = u;
            nxt[cnt] = head[v];
            cap[cnt] = 0;
            head[v] = cnt;
        }

        queue<int> q;

        bool bfs() {
            memset(depth, 0, sizeof(depth));
            depth[s] = 1;
            q.push(s);
            while(!q.empty()) {
                int u = q.front();
                q.pop();
                for ( int i = head[u]; i; i = nxt[i] ) {
                    int v = edge[i];
                    if(depth[v]) {
                        continue;
                    }
                    if(cap[i]) {
                        depth[v] = depth[u] + 1;
                        q.push(v);
                    }
                }
            }
            return depth[t];
        }

        int dfs(int u, int dist) {
            if(== t) {
                return dist;
            }
            int flow = 0;
            for ( int i = head[u]; i && dist; i = nxt[i] ) {
                if(cap[i] == 0)
                    continue;
                int v = edge[i];
                if(depth[v] != depth[u] + 1) {
                    continue;
                }
                int res = dfs(v, min(cap[i], dist));
                cap[i] -= res;
                cap[^ 1] += res;
                //printf("cap[%d]:%d ",t, cap[t]);
                dist -= res;
                flow += res;
            }
            return flow;
        }

        int maxflow() {
            int ans = 0;
            while(bfs()) {
                ans += dfs(s, inf);
            }
            return ans;
        }
    } dinic;

    int main()
    {
        //freopen("data.txt", "r", stdin);
        int k;
        read(k); read(n);
        dinic.init();
        s = 0, t = n + k + 1;
        int x;
        for ( int i = 1; i <= k; ++) {
            read(x);
            m += x;
            dinic.BuildGraph(+ i, t, x);
        }
        for ( int i = 1; i <= n; ++) {
            dinic.BuildGraph(s, i, 1);
            int p;
            read(p);
            for ( int j = 1; j <= p; ++) {
                read(x);
                dinic.BuildGraph(i, x + n, 1);
            }
        }
        int tot = dinic.maxflow();
        //dbg(tot);
        if(tot != m) {
            puts("No Solution!");
        }
        else {
            for ( int i = 1; i <= k; ++) {
                int u = n + i;
                printf("%d:",i);
                for ( int j = dinic.head[u]; j; j = dinic.nxt[j] ) {
                    int v = dinic.edge[j];
                    if(dinic.cap[j] && v <= n) {
                        printf(" %d",v);
                    }
                }
                printf(" ");
            }
        }
        return 0;
    }
  • 相关阅读:
    [DB] 数据库的连接
    JS leetcode 翻转字符串里的单词 题解分析
    JS leetcode 拥有最多糖果的孩子 题解分析,六一快乐。
    JS leetcode 搜索插入位置 题解分析
    JS leetcode 杨辉三角Ⅱ 题解分析
    JS leetcode 寻找数组的中心索引 题解分析
    JS leetcode 移除元素 题解分析
    JS leetcode 最大连续1的个数 题解分析
    JS leetcode 两数之和 II
    JS leetcode 反转字符串 题解分析
  • 原文地址:https://www.cnblogs.com/orangeko/p/12723543.html
Copyright © 2011-2022 走看看