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;
    }
  • 相关阅读:
    python+selenium环境搭建以及遇到的坑
    (二)第一个测试用例
    (一)TestNG介绍与安装
    Appium详解server capabilities
    Mac安装MySQL数据库
    POI 设置单元格样式
    JAVA_HOME环境变量失效的解决办法
    svn linux 命令
    StringUtils工具类的常用方法
    ArrayUtils 方法
  • 原文地址:https://www.cnblogs.com/orangeko/p/12723543.html
Copyright © 2011-2022 走看看