• 网络流24题——试题库问题


    题目链接:luogu2763

    题目描述

    «问题描述:

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

    «编程任务:

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

    输入输出格式

    输入格式:

    第1行有2个正整数k和n (2 <=k<= 20, k<=n<= 1000)

    k 表示题库中试题类型总数,n 表示题库中试题总数。第2 行有k 个正整数,第i 个正整数表示要选出的类型i的题数。这k个数相加就是要选出的总题数m。接下来的n行给出了题库中每个试题的类型信息。每行的第1 个正整数p表明该题可以属于p类,接着的p个数是该题所属的类型号。

    输出格式:

    第i 行输出 “i:”后接类型i的题号。如果有多个满足要求的方案,只要输出1个方案。如果问题无解,则输出“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
    这个题与圆桌游戏基本是一样的,对于每个试题i,如果i可以属于p类,就将p向其连一条流量为1的边。然后按照惯例设一个源点S和汇点T,从S向每个题库连一个流量为题库所需试题多少的边。
    然后将每道题与汇点连一条容量为1的边。跑一边最大流,如果最大流等于每个题库的要求量之和,那么就有解,否则无解。然后去遍历每个题库所连的边,如果这些边的容量变为了0。那么就说明这条边所连向的题可以属于这个题库,将其输出即可。
    代码:
      1 #include<cstdio>
      2 #include<iostream>
      3 #include<cstring>
      4 #include<queue>
      5 using namespace std;
      6 const int N=10600*2,INF=0x7fffffff;
      7 queue<int>q;
      8 int k,n,head[N],S,T,ejs,W,dep[N];
      9 char ch;
     10 char buf[1000000],*p1=buf,*p2=buf;
     11 #define nc() 
     12     p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2) ? EOF :*p1++;
     13 #define read(x)  
     14     x=0;ch=nc(); 
     15     while(!isdigit(ch)) ch=nc();
     16     while(isdigit(ch))x=x*10+ch-'0',ch=nc();
     17 inline int change(int x)
     18 {
     19     return x%2?x+1:x-1;
     20 }
     21 struct node
     22 {
     23     int v,nxt,w;
     24 }edg[N];
     25 void add(int u,int v,int w)
     26 {
     27     edg[++ejs].v=v;edg[ejs].w=w;edg[ejs].nxt=head[u];head[u]=ejs;
     28     edg[++ejs].v=u;edg[ejs].w=0;edg[ejs].nxt=head[v];head[v]=ejs;
     29 }
     30 bool bfs()
     31 {
     32     memset(dep,0,sizeof(dep));
     33     while(!q.empty()) q.pop();
     34     q.push(S);
     35     dep[S]=1;
     36     while(!q.empty())
     37     {
     38         int u=q.front();
     39         q.pop();
     40         for(int i=head[u];i;i=edg[i].nxt)
     41         {
     42             int v=edg[i].v;
     43             if(!dep[v]&&edg[i].w)
     44             {
     45                 dep[v]=dep[u]+1;
     46                 q.push(v);
     47                 if(v==T) return 1; 
     48             }
     49         }
     50     }
     51     return 0;
     52 }
     53 int dfs(int u,int dist)
     54 {
     55     if(u==T) return dist;
     56     int di=0;
     57     for(int i=head[u];i;i=edg[i].nxt)
     58     {
     59         int v=edg[i].v;
     60         if(di==dist) return di;
     61         if(edg[i].w&&dep[v]==dep[u]+1)
     62         {
     63             int kk=dfs(v,min(dist,edg[i].w));
     64             if(kk)
     65             {
     66                 di+=kk;
     67                 edg[i].w-=kk;
     68                 edg[change(i)].w+=kk;    
     69             }
     70         }
     71     }
     72     return di;
     73 }
     74 int dinic()
     75 {
     76     int kk,ans=0;
     77     while(bfs())
     78     {
     79         kk=dfs(S,INF);
     80         while(kk)
     81         {
     82             ans+=kk;
     83             kk=dfs(S,INF);
     84         }
     85     }
     86     return ans;
     87 }
     88 int main()
     89 {
     90     //freopen("data4.in","r",stdin);
     91     read(k);
     92     read(n);
     93     n+=k;
     94     S=0,T=n+1;
     95     for(int i=1;i<=k;++i)
     96     {
     97         int x;
     98         read(x);
     99         W+=x;
    100         add(S,i,x);
    101     }
    102     for(int i=k+1;i<=n;++i)
    103     {
    104         int p;
    105         read(p);
    106         for(int j=1;j<=p;++j)
    107         {
    108             int x;
    109             read(x);
    110             add(x,i,1);
    111         }
    112     }
    113     for(int i=k+1;i<=n;++i)
    114         add(i,T,1);
    115     if(dinic()!=W)
    116     {
    117         printf("No Solution!");
    118         return 0;
    119     }
    120     for(int i=1;i<=k;++i)
    121     {
    122         printf("%d: ",i);
    123         for(int j=head[i];j;j=edg[j].nxt)
    124         {
    125             int v=edg[j].v;
    126             if(!edg[j].w&&v!=S)
    127             printf("%d ",v-k);
    128         }
    129         printf("
    ");
    130     }
    131     return 0;
    132 } 
    luogu2763
    
    
    


  • 相关阅读:
    PHP Cookbook读书笔记 – 第18章安全和加密
    ANDROID开发之http调试常见错误
    GD库之有意思的imagesetstyle
    PHP Cookbook读书笔记 – 第06章函数
    PHP Cookbook读书笔记 – 第09章表单
    PHP Cookbook读书笔记 – 第04章数组
    PHP Cookbook读书笔记 – 第17章图形
    PHP常见面试问题
    SQL SERVER 表分区实施步奏
    PHP Cookbook读书笔记 – 第12章XML
  • 原文地址:https://www.cnblogs.com/wxyww/p/9356182.html
Copyright © 2020-2023  润新知