传送门

呜呜,好感动,这这真是网络流的清流啊

被感动哭了

− − − − − − − − − − − − − − − − − − − − − − − − − − − − \color{Red}----------------------------

分析一下题目,就大概知道只一个类似二分图匹配的问题

我 们 把 m 个 单 位 放 在 左 边 , n 个 桌 子 放 在 右 边 我们把m个单位放在左边,n个桌子放在右边 m,n

由于每个单位的人只能在任意一张桌子上做一个人

结 论 : 每 个 单 位 向 每 个 桌 子 连 一 条 流 量 为 1 的 边 \color{Red}结论:每个单位向每个桌子连一条流量为1的边 :1

每个单位只有 r [ i ] r[i] r[i]个人

结 论 : 源 点 向 每 个 单 位 连 一 条 流 量 r [ i ] 的 边 \color{Red}结论:源点向每个单位连一条流量r[i]的边 :r[i]

每个桌子只容纳 c [ i ] 个 人 c[i]个人 c[i]

结 论 : 每 个 桌 子 向 源 点 连 一 条 流 量 c [ i ] 的 边 \color{Red}结论:每个桌子向源点连一条流量c[i]的边 :c[i]

连 的 这 些 边 都 是 起 到 一 个 限 制 作 用 , 只 要 从 s 到 t 的 路 线 流 量 在 范 围 内 就 合 法 连的这些边都是起到一个限制作用,只要从s到t的路线流量在范围内就合法 ,st线

至于方案,枚举每个单位的所有边,如果流量为0说明选了对应的桌子

#include <bits/stdc++.h>
using namespace std;
const int maxn=2e5+10;
const int inf=1e9;
int n,m,s,t,r[maxn],c[maxn],dis[maxn],sumn;
struct edge{
	int to,flow,nxt;
}d[maxn]; int head[maxn],cnt=1;
void add(int u,int v,int flow){
	d[++cnt]=(edge){v,flow,head[u]},head[u]=cnt;
}
bool bfs()
{
	queue<int>q;
	for(int i=0;i<=t;i++)	dis[i]=0;
	dis[s]=1;
	q.push( s );
	while( !q.empty() )
	{
		int u=q.front(); q.pop();
		for(int i=head[u];i;i=d[i].nxt )
		{
			int v=d[i].to;
			if( dis[v]==0&&d[i].flow )
			{
				dis[v]=dis[u]+1;
				if( v==t )	return true;
				q.push( v );
			}
		}
	}
	return false;
}
int dinic(int u,int flow)
{
	if( u==t )	return flow;
	int res=flow;
	for(int i=head[u];i&&res;i=d[i].nxt)
	{
		int v=d[i].to;
		if( dis[v]==dis[u]+1&&d[i].flow )
		{
			int temp=dinic(v,min(res,d[i].flow) );
			if( temp==0 )	dis[v]=0;
			res-=temp;
			d[i].flow-=temp;
			d[i^1].flow+=temp;
		}
	}
	return flow-res;
}
int main()
{
	cin >> m >> n;
	s=0,t=n+m+1;
	for(int i=1;i<=m;i++)
	{
		cin >> r[i];
		sumn+=r[i];
		add( s,i,r[i] );	add( i,s,0 );
	}
	for(int i=1;i<=n;i++)
	{
		cin >> c[i];
		add(i+m,t,c[i] );	add(t,i+m,0 );
	}
	for(int i=1;i<=m;i++)
	for(int j=1;j<=n;j++)
		add(i,j+m,1),add(j+m,i,0);
	int ans=0;
	while( bfs() )	ans+=dinic(s,inf);
	if( ans!=sumn )	cout << 0;
	else
	{
		cout << 1 << '\n';
		for(int i=1;i<=m;i++)
		{
			for(int j=head[i];j;j=d[j].nxt)
			{
				int v=d[j].to;
				if( !d[j].flow&&v!=s )	cout << v-m << " ";
			}
			cout << '\n';
		}
	}
}