题意说的有问题啊。。。
应该是每种类型至少有p题,因为一道题可以向多个类型做贡献。
将源点向每题连流量为1的边,代表选一本
将每题向各种连流量为1的边,表示只能对其中一种有贡献
将每种向汇点连流量为需求的边。
记录答案第二种边判断即可
By:大奕哥
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=1100,inf=1e9; 4 int s=0,t=1050,cnt=-1,head[N],v[N],k,n,m; 5 struct node{ 6 int to,nex,w; 7 }e[100005]; 8 void add(int x,int y,int w) 9 { 10 e[++cnt].to=y;e[cnt].nex=head[x];head[x]=cnt;e[cnt].w=w; 11 e[++cnt].to=x;e[cnt].nex=head[y];head[y]=cnt;e[cnt].w=0; 12 } 13 queue<int>q; 14 bool bfs(int x,int y) 15 { 16 memset(v,-1,sizeof(v)); 17 v[x]=0;q.push(x); 18 while(!q.empty()) 19 { 20 int x=q.front();q.pop(); 21 for(int i=head[x];i!=-1;i=e[i].nex) 22 { 23 int y=e[i].to; 24 if(v[y]!=-1||e[i].w==0)continue; 25 v[y]=v[x]+1;q.push(y); 26 } 27 } 28 return v[y]!=-1; 29 } 30 int dfs(int x,int w,int yy) 31 { 32 if(x==yy||!w)return w; 33 int s=0; 34 for(int i=head[x];i!=-1;i=e[i].nex) 35 { 36 int y=e[i].to; 37 if(v[y]!=v[x]+1||!e[i].w)continue; 38 int flow=dfs(y,min(w-s,e[i].w),yy); 39 if(!flow)v[y]=-1; 40 e[i].w-=flow;e[i^1].w+=flow; 41 s+=flow; 42 if(s==w)return s; 43 } 44 return s; 45 } 46 int dinic() 47 { 48 int ans=0; 49 while(bfs(s,t)) 50 { 51 ans+=dfs(s,inf,t); 52 } 53 return ans; 54 } 55 int num[25],p[N],bel[N][N]; 56 int main() 57 { 58 scanf("%d%d",&k,&n); 59 memset(head,-1,sizeof(head)); 60 for(int i=1;i<=k;++i) 61 { 62 scanf("%d",&num[i]); 63 add(i+n,t,num[i]); 64 } 65 for(int i=1;i<=n;++i) 66 { 67 scanf("%d",&p[i]); 68 for(int j=1;j<=p[i];++j) 69 scanf("%d",&bel[i][j]),add(i,bel[i][j]+n,1); 70 add(s,i,1); 71 } 72 int ans=dinic(); 73 if(ans<m){puts("No Solution!");return 0;} 74 for(int i=1;i<=k;++i) 75 { 76 printf("%d: ",i); 77 for(int j=head[i+n];j!=-1;j=e[j].nex) 78 { 79 int y=e[j].to; 80 if(!e[j].w)continue; 81 printf("%d ",y); 82 } 83 printf(" "); 84 } 85 return 0; 86 }