从s向每个单位连一条容量为ri的边,从每个餐桌向汇点连一条容量为ci的边,每个单位与每个餐桌之间连一条容量为1的边,最大流即为答案。
// q.c
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#define mem(a) memset(a,0,sizeof(a))
using namespace std;
const int M=300,INF=(int)1e9;
struct Edge {
int v,nex,flow,cap; Edge() {}
Edge(int a,int b,int c,int d):v(a),nex(b),flow(c),cap(d) {}
}ed[M*M];
int cnt,head[M<<1];
void add_edge(int a,int b,int c) {
ed[cnt]=Edge(b,head[a],0,c); head[a]=cnt++;
ed[cnt]=Edge(a,head[b],0,0); head[b]=cnt++;
}
struct Dinic {
int n,s,t,dis[M<<1],cur[M<<1]; queue<int> Q;
Dinic():n(0),s(0),t(0) {
mem(dis); mem(cur);
while(!Q.empty()) Q.pop();
}
bool bfs() {
mem(dis); dis[s]=1; Q.push(s);
int u,i; Edge e;
while(!Q.empty()) {
u=Q.front(); Q.pop();
for(i=head[u];i!=-1;i=ed[i].nex) {
e=ed[i];
if(!dis[e.v]&&e.cap>e.flow) {
dis[e.v]=dis[u]+1;
Q.push(e.v);
}
}
}
return dis[t];
}
int dfs(int u,int lim) {
if(u==t||!lim) return lim;
int f=0,tmp=0; Edge e;
for(int &i=cur[u];i!=-1;i=ed[i].nex) {
e=ed[i];
if(dis[e.v]==dis[u]+1) {
f=dfs(e.v,min(lim,e.cap-e.flow));
if(f>0) {
ed[i].flow+=f; tmp+=f;
ed[i^1].flow-=f; lim-=f;
if(!lim) break;
}
}
}
return tmp;
}
int solve(int x,int y,int z) {
s=x; t=y; n=z; int ans=0;
while(bfs()) {
for(int i=0;i<=n;i++) cur[i]=head[i];
ans+=dfs(s,INF);
}
return ans;
}
}DC;
int main() {
freopen("roundtable.in","r",stdin);
freopen("roundtable.out","w",stdout);
memset(head,-1,sizeof(head));
int m,n,x,sum=0,ans=0;
scanf("%d%d",&m,&n);
for(int i=1;i<=m;i++) {
scanf("%d",&x);
sum+=x;
add_edge(0,i,x);
}
for(int i=1;i<=n;i++) {
scanf("%d",&x);
add_edge(i+m,n+m+1,x);
}
for(int i=1;i<=m;i++) for(int j=1;j<=n;j++)
add_edge(i,j+m,1);
ans=DC.solve(0,n+m+1,n+m+1);
if(ans==sum) {
printf("1\n"); Edge e;
for(int i=1;i<=n;i++) {
for(int j=head[i];j!=-1;j=ed[j].nex) {
e=ed[j];
if(e.flow==1) printf("%d ",e.v-m);
}
printf("\n");
}
}else printf("0\n");
return 0;
}