分析:每个代表团的人数为ai,建(s,i,ai),每张桌子能容纳bj,建(j,t,bj)。每个代表团对所有桌子建(i,j,1),跑最大流判断是否满流。
输出方案:遍历网络图每条跑满的边,用桶记录的答案。
#include
using namespace std;
const int maxn = 1e3 + 10;
const int maxm = 2e5 + 10;
const int inf = 0x3f3f3f3f;
struct ss{
int u,v,w,nxt;
}edg[maxm];
int head[maxn],cnt,d[maxn],a[maxn],dp[maxn],n,m;
vector<int> g[maxn];
void init() {
cnt = 0;
memset(head,-1,sizeof head);
}
void add(int u,int v,int w) {
edg[cnt].v = v;
edg[cnt].u = u;
edg[cnt].w = w;
edg[cnt].nxt = head[u];
head[u] = cnt++;
}
bool bfs(int s,int t) {
queue<int> q;
memset(d,0,sizeof d);
q.push(s);
d[s] = 1;
while(!q.empty()) {
int top = q.front();
q.pop();
for(int i = head[top]; i + 1; i = edg[i].nxt) {
int v = edg[i].v,w = edg[i].w;
if(!d[v] && w) {
d[v] = d[top] + 1;
q.push(v);
}
}
}
return d[t] > 0;
}
int dfs(int s,int t,int inflow) {
if(s == t || !inflow) return inflow;
int flow = 0;
for(int i = head[s]; i + 1; i = edg[i].nxt) {
int v = edg[i].v,w = edg[i].w;
if(w && d[v] == d[s] + 1) {
int x = dfs(v,t,min(inflow,w));
edg[i].w -= x;edg[i ^ 1].w += x;
inflow -= x;flow += x;
if(!inflow) break;
}
}
if(!flow) d[s] = -2;
return flow;
}
int dinic(int s,int t) {
int ans = 0;
while(bfs(s,t))
ans += dfs(s,t,inf);
return ans;
}
int main() {
init();
scanf("%d%d",&n,&m);
int s = 0,t = n + m + 1,x,sum = 0;
for(int i = 1; i <= n; i++) {
scanf("%d",&x);
sum += x;
add(s,i,x);
add(i,s,0);
}
for(int i = 1; i <= m; i++) {
scanf("%d",&x);
add(i + n,t,x);
add(t, i + n,x);
}
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++) {
add(i,j + n,1);
add(j + n,i,0);
}
int tot = dinic(s,t);
if(tot < sum)
puts("0");
else {
puts("1");
for(int i = 0; i < cnt; i++)
if(edg[i].w == 0) g[edg[i].u].push_back(edg[i].v - n);
for(int i = 1; i <= n; i++) {
for(int j = 0;j < g[i].size(); j++) {
if(j) printf(" ");
printf("%d",g[i][j]);
}
puts("");
}
}
return 0;
}