原题:https://www.luogu.org/problemnew/show/P2763
题解:其实就是就是n个试题和k配对。建图方法: S连i(i∈n), j连T(j∈k),且边的流量是a[i]。如题连i->j就行了。跑一边最大流,从k枚举,输出答案。然而洛谷上要英文冒号。
#include<bits/stdc++.h>
#define inf 0x7fffffff
using namespace std;
const int N=2200;
const int M=220000;
struct E{int to,w,nxt;}data[M<<1];
int len,n,k,S,T,sum;
int h[N],dep[N],cur[N];
queue<int> q;
inline int rd(){
int x=0;int f=1;char s=getchar();
while(!isdigit(s)) f=(s=='-'?-1:f),s=getchar();
while(isdigit(s)) x=(x<<1)+(x<<3)+s-'0',s=getchar();
return x*f;
}
inline void ins(int x,int y,int w){
data[++len].to=y;data[len].w=w;data[len].nxt=h[x];h[x]=len;
data[++len].to=x;data[len].w=0;data[len].nxt=h[y];h[y]=len;
}
bool bfs(){
memset(dep,0,sizeof dep);
dep[S]=1;q.push(S);
while(!q.empty()){
int x=q.front();q.pop();
for(int i=h[x];i;i=data[i].nxt){
int y=data[i].to;int w=data[i].w;
if(!dep[y] && w!=0){
dep[y]=dep[x]+1;q.push(y);
}
}
}
return dep[T];
}
int dfs(int x,int lim){
if(x==T) return lim;
for(int &i=cur[x];i;i=data[i].nxt){
int y=data[i].to;int w=data[i].w;
if(dep[y]==dep[x]+1 && w!=0){
int di=dfs(y,min(lim,w));
if(di){
data[i^1].w+=di;
data[i].w-=di;
return di;
}
}
}
return 0;
}
inline int dinic(){
int ans=0;
while(bfs()){
for(int i=S;i<=T;i++) cur[i]=h[i];
while(int k=dfs(S,inf)) ans+=k;
}
return ans;
}
int main(){
// freopen("testdata.in","r",stdin);
k=rd();n=rd();len=1;S=0;T=n+k+1;sum=0;
for(int i=1,x;i<=k;i++) x=rd(),ins(i+n,T,x),sum+=x;
for(int i=1,x;i<=n;i++) {
int cnt=rd();ins(S,i,1);
while(cnt--) x=rd(),ins(i,x+n,1);
}
int ans=dinic();
if(sum!=ans){printf("No Solution!\n");return 0;}
for(int x=1;x<=k;x++){
printf("%d: ",x);
for(int i=h[x+n];i;i=data[i].nxt){
int y=data[i].to;int w=data[i].w;
if(w && y!=T) printf("%d ",y);
}
printf("\n");
}
return 0;
}