前置知识
题意
题目描述
假设一个试题库中有 n n n道试题。每道试题都标明了所属类别。同一道题可能有多个类别属性。现要从题库中抽取 m m m 道题组成试卷。并要求试卷包含指定类型的试题。试设计一个满足要求的组卷算法。
对于给定的组卷要求,计算满足要求的组卷方案。
输入输出格式
输入格式:
第 1 1 1行有 2 2 2个正整数 k k k和 n n n ( 2 < = k < = 20 , k < = n < = 1000 ) (2<=k<=20, k<=n<=1000) (2<=k<=20,k<=n<=1000)
k k k 表示题库中试题类型总数, n n n 表示题库中试题总数。第 2 2 2 行有 k k k 个正整数,第 i i i 个正整数表示要选出的类型i的题数。这 k k k个数相加就是要选出的总题数 m m m。接下来的 n n n行给出了题库中每个试题的类型信息。每行的第 1 1 1 个正整数 p p p表明该题可以属于 p p p类,接着的 p p p个数是该题所属的类型号。
输出格式:
第 i i i 行输出 “ i : ” “i:” “i:”后接类型 i i i的题号。如果有多个满足要求的方案,只要输出 1 1 1个方案。如果问题无解,则输出“No Solution!”。
总体思路
S S S到试题类型连一条容量为所选题数的边,试题类型到试题编号连容量为 1 1 1的边,试题编号到 T T T连容量为 1 1 1的边,跑最大流,最后扫描残量网络得出解。
代码
#include<bits/stdc++.h>
using namespace std;
int first[10005],nxt[10005],to[10005],w[10005],dep[10005],cnt[10005],s,t,tot=1,n,k,Cnt=0;
int ans[25][1005],ind[25];
int Read(){
int x=0,f=1;
char ch=getchar();
while(!isdigit(ch)){
if(ch=='-') f=-1;
ch=getchar();
}
while(isdigit(ch)){
x=(x<<3)+(x<<1)+ch-'0';
ch=getchar();
}
return x*f;
}
void Add(int x,int y,int z){
nxt[++tot]=first[x];
first[x]=tot;
to[tot]=y;
w[tot]=z;
}
void bfs(int S){
memset(dep,0xff,sizeof(dep));
dep[S]=0;
cnt[0]=1;
queue<int> q;
q.push(S);
while(!q.empty()){
int u=q.front();
q.pop();
for(int e=first[u];e;e=nxt[e]){
int v=to[e];
if(dep[v]==-1){
++cnt[dep[v]=dep[u]+1];
q.push(v);
}
}
}
}
int mf=0;
int dfs(int p,int f){
if(p==t){
mf+=f;
return f;
}
int u=0;
for(int e=first[p];e;e=nxt[e]){
if(w[e]&&dep[to[e]]==dep[p]-1){
int uu=dfs(to[e],min(w[e],f-u));
if(uu){
w[e]-=uu;
w[e^1]+=uu;
u+=uu;
}
if(u==f) return u;
}
}
if(!--cnt[dep[p]]){
dep[s]=n+k+10;
}
++cnt[++dep[p]];
return u;
}
void bfs2(){
queue<int> q;
for(int e=first[s];e;e=nxt[e]){
q.push(to[e]);
}
while(!q.empty()){
int u=q.front();
q.pop();
for(int e=first[u];e;e=nxt[e]){
int v=to[e];
if(w[e]==0&&v!=s){
ans[u][++ind[u]]=v;
}
}
}
}
signed main(){
k=Read(),n=Read();
s=0,t=2005;
for(int i=1;i<=k;i++){
int x;
x=Read();
Cnt+=x;
Add(s,i,x);
Add(i,s,0);
}
for(int i=1;i<=n;i++){
int x,y;
x=Read();
for(int j=1;j<=x;j++){
y=Read();
Add(y,i+25,1);
Add(i+25,y,0);
}
}
for(int i=1;i<=n;i++){
Add(i+25,t,1);
Add(t,i+25,0);
}
bfs(t);
while(dep[s]<k+n+9){
dfs(s,0x3fffffff);
}
if(mf<Cnt){
cout<<"No Solution!\n";
return 0;
}
bfs2();
for(int i=1;i<=k;i++){
cout<<i<<":";
for(int j=1;j<=ind[i];j++){
cout<<" "<<ans[i][j]-25;
}
cout<<endl;
}
return 0;
}