试题库问题

题目描述

«问题描述:

假设一个试题库中有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!”。

输入输出样例

输入样例#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,因为只有一道,最后连向汇点。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include<bits/stdc++.h>
#define REP(i, a, b) for(int i = (a); i <= (b); ++ i)
#define REP(j, a, b) for(int j = (a); j <= (b); ++ j)
#define PER(i, a, b) for(int i = (a); i >= (b); -- i)
using namespace std;
template <class T>
inline void rd(T &ret){
    char c;
    ret = 0;
    while ((c = getchar()) < '0' || c > '9');
    while (c >= '0' && c <= '9'){
        ret = ret * 10 + (c - '0'), c = getchar();
    }
}
const int maxn=1e5+5;
struct node{int v,val,nx;}p[maxn];
int k,n,s,t,tot,m,tmp,cur,ans,depth[maxn],head[maxn];
void add(int u,int v,int w){
    p[++tot].val=w,p[tot].v=v,p[tot].nx=head[u],head[u]=tot;
}
queue<int>q;
int bfs(){
       q.push(s);
       memset(depth,0,sizeof(depth));
       depth[s]=1;
       while(q.size()){
            int now=q.front();
            q.pop();
            for(int i=head[now];i;i=p[i].nx){
                 int v=p[i].v;
                 if(!depth[v]&&p[i].val>0){
                    depth[v]=depth[now]+1;
                    q.push(v);
                 }
            }
       }
       return depth[t];
}
int dfs(int u,int c){
       if(u==t||!c)return c;
       int qe=0;
       for(int i=head[u];i;i=p[i].nx){
             int to=p[i].v;
             if(depth[to]==depth[u]+1&&p[i].val>0){
                  int ac=dfs(to,min(c,p[i].val));
                  if(ac>0){
                      p[i].val-=ac,p[i^1].val+=ac;
                      c-=ac,qe+=ac;
                      if(!c)return qe;
                  }
             }
       }
       return qe;
}
int dinic(){
     while(bfs())ans+=dfs(s,0x3f3f3f3f);
     return ans;
}
int main(){
     rd(k),rd(n),t=k+n+1;
     for(int i=1;i<=k;i++){
          rd(tmp),m+=tmp,add(s,i,tmp),add(i,s,0);
     }
     for(int i=1;i<=n;i++){
         rd(cur);
         for(int j=1;j<=cur;j++){
            rd(tmp),add(tmp,i+k,1),add(i+k,tmp,0);
         }
     }
     for(int i=1;i<=n;i++)add(i+k,t,1),add(t,i+k,0);
     if(dinic()==m){
        for(int i=1;i<=k;i++){
          cout<<i<<": ";
          for(int j=head[i];j;j=p[j].nx){
               if(p[j].v>0&&!p[j].val){
                    cout<<p[j].v-k<<' ';
               }
          }
          cout<<endl;
        }
     }
     else cout<<"No Solution!"<<endl;
     return 0;
}
原文地址:https://www.cnblogs.com/czy-power/p/10390414.html