• liberOJ#6006. 「网络流 24 题」试题库 网络流, 输出方案


    #6006. 「网络流 24 题」试题库

     
     

    题目描述

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

    输入格式

    第 1 11 行有 2 22 个正整数 k kk 和 n nn。k kk 表示题库中试题类型总数,n nn 表示题库中试题总数。第 2 22 行有 k kk 个正整数,第 i ii 个正整数表示要选出的类型 i ii 的题数。这 k kk 个数相加就是要选出的总题数 m mm。

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

    输出格式

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

    样例

    样例输入

    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 6 8
    2: 7 9 10
    3: 2 3 4 5

    数据范围与提示

    2≤k≤20,k≤n≤1000 2 leq k leq 20, k leq n leq 10002k20,kn1000

    题解:

      wannafly题解

      建立二分图,每个类别为X集合中的顶点,每个题为Y集合中的顶点,增设附加源S和汇T。

      1、从S向每个Xi连接一条容量为该类别所需数量的有向边。
      2、从每个Yi向T连接一条容量为1的有向边。
      3、如果一个题i属于一个类别j,连接一条从Xj到Yi容量为1的有向边。

      求网络最大流,如果最大流量等于所有类别所需之和,则存在解,否则无解。对于每个类别,从X集合对应点出发的所有满流边,指向的B集合中的顶点就是该类别的所选的题(一个可行解)。

    #include<bits/stdc++.h>
    using namespace std;
    #pragma comment(linker, "/STACK:102400000,102400000")
    #define ls i<<1
    #define rs ls | 1
    #define mid ((ll+rr)>>1)
    #define pii pair<int,double>
    #define MP make_pair
    typedef long long LL;
    typedef unsigned long long ULL;
    const long long INF = 1e18+1LL;
    const double pi = acos(-1.0);
    const int N = 1e5+10, M = 1e3+20,inf = 2e9;
    
    int head[N],t=2,h[N],q[N],S,T,ans = 0;
    struct edge{int to,next,v;}e[N * 2];
    void adds(int u,int v,int w)
     {e[t].to=v;e[t].v=w;e[t].next=head[u];head[u]=t++;}
    void add(int u,int v,int w) {adds(u,v,w);adds(v,u,0);}
    int bfs() {
        memset(h,-1,sizeof(h));
        int l=0,r=1,now;
        q[l]=S;
        h[S]=0;
        while(l!=r){
            now=q[l++];if(l == 100000) l=0;
            for(int i=head[now];i!=-1;i=e[i].next) {
                if(e[i].v&&h[e[i].to]==-1) {
                    h[e[i].to]=h[now]+1;
                    q[r++]=e[i].to;
                    if(r==100000) r = 0;
                }
            }
        }
        if(h[T]==-1) return 0;
        else return 1;
    }
    int dfs(int x,int f) {
            if(x == T) return f;
            int used=0,w;
            for(int i=head[x]; i!=-1;i=e[i].next) {
                if(e[i].v&&h[e[i].to] == h[x] + 1) {
                    w=dfs(e[i].to,min(f-used,e[i].v));
                    used+=w;e[i].v-=w;e[i^1].v+=w;
                    if(used == f) return f;
                }
            }
            return used;
    }
    void dinic() {while(bfs()) ans+=dfs(S,inf);}
    
    int k,n,a[N];
    vector<int  >G[N];
    int main() {
        scanf("%d%d",&k,&n);S = 2*(n+k)+1,T = S+1;
        t = 2;memset(head,-1,sizeof(head));
        int sum = 0;
        for(int i = 1; i <= k; ++i) {
            scanf("%d",&a[i]);
            add(S,i,a[i]);
            sum += a[i];
        }
        for(int i = 1; i <= n; ++i) {
            int x,y;
            scanf("%d",&x);
            for(int j = 1; j <= x; ++j) {
                scanf("%d",&y);
                add(y,i+k,1);
            }
            add(i+k,T,1);
        }
        ans = 0;
        dinic();
        if(ans != sum) puts("No Solution!");
        else {
            for(int i = 1; i <= k; ++i) {
                printf("%d:",i);
                for(int j = head[i]; j!=-1; j = e[j].next) {
                    if(e[j].v == 0 && e[j].to!=S) {
                        printf(" %d",e[j].to - k);
                    }
                }
                printf("
    ");
            }
        }
        return 0;
    }

     

  • 相关阅读:
    DVS6446教程链接
    今晚做的二值化和分割
    Sybase ETL
    QR码的结构
    cannot open file Default/configPkg/linker.cmd 错误
    QR 码的位置检测符
    QR Code
    C6000 OMAP DAVINCI的关系
    Davinci笔记 DSP子系统 VS ARM子系统
    ETL简介
  • 原文地址:https://www.cnblogs.com/zxhl/p/7250654.html
Copyright © 2020-2023  润新知