题解:源点向单位建容量为单位人数的边,桌子向汇点建容量为桌子最多容纳多少人的边,单位向所有桌子连容量为1的边,跑最大流。
如果最大流等于单位总人数则有解,输出满流边即为方案。
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=450,M=(150*270+N)*2,inf=1e9; 4 int h[N],e[M],ne[M],f[M],idx; 5 int cur[N],d[N]; 6 int n,m,S,T; 7 void add(int a,int b,int c) 8 { 9 ne[idx]=h[a],e[idx]=b,f[idx]=c,h[a]=idx++; 10 ne[idx]=h[b],e[idx]=a,f[idx]=0,h[b]=idx++; 11 } 12 bool bfs() 13 { 14 memset(d,-1,sizeof d); 15 queue<int>q; 16 d[S]=0; 17 q.push(S); 18 cur[S]=h[S]; 19 while(q.size()) 20 { 21 int t=q.front(); 22 q.pop(); 23 for(int i=h[t];i!=-1;i=ne[i]) 24 { 25 int j=e[i]; 26 if(d[j]==-1&&f[i]) 27 { 28 d[j]=d[t]+1; 29 cur[j]=h[j]; 30 if(j==T)return true; 31 q.push(j); 32 } 33 } 34 } 35 return false; 36 } 37 int find(int u,int limit) 38 { 39 if(u==T)return limit; 40 int flow=0; 41 for(int i=cur[u];i!=-1&&flow<limit;i=ne[i]) 42 { 43 int j=e[i]; 44 cur[u]=i; 45 if(d[j]==d[u]+1&&f[i]) 46 { 47 int t=find(j,min(f[i],limit-flow)); 48 if(!t)d[j]=-1; 49 f[i]-=t,f[i^1]+=t,flow+=t; 50 } 51 } 52 return flow; 53 } 54 int dinic() 55 { 56 int r=0,flow; 57 while(bfs())while(flow=find(S,inf))r+=flow; 58 return r; 59 } 60 int main() 61 { 62 memset(h,-1,sizeof h); 63 cin>>m>>n; 64 S=0,T=N-1; 65 int tot=0; 66 for(int i=1;i<=m;i++) 67 { 68 int x; 69 scanf("%d",&x); 70 add(S,i,x); 71 tot+=x; 72 } 73 for(int i=1;i<=n;i++) 74 { 75 int x; 76 scanf("%d",&x); 77 add(m+i,T,x); 78 } 79 for(int i=1;i<=m;i++) 80 for(int j=1;j<=n;j++) 81 add(i,m+j,1); 82 if(tot!=dinic())puts("0"); 83 else 84 { 85 puts("1"); 86 for(int i=1;i<=m;i++) 87 { 88 for(int j=h[i];j!=-1;j=ne[j]) 89 { 90 int b=e[j]; 91 if(b>=m+1&&b<=n+m&&!f[j]) 92 printf("%d ",b-m); 93 } 94 printf(" "); 95 } 96 } 97 }