题目链接
https://www.luogu.org/problemnew/show/P3254
圆桌问题
与前一道试题库问题非常的向,我们借鉴他的思想,我们设单位的集合为A,桌子的集合为B,对于每个单位人数x,从S向A连一条流量为x的边,对于每张桌子能坐y个人,我们从B向T连流量为y的边,那么每一条S-A-B-T的路径表示这个单位的人坐在B这张桌子上,由于每张桌子每个单位只能坐一个人,所以所有A向所有B连流量为1的边,就做完了。
#include<cstdio>
#include<algorithm>
#include<cctype>
#include<cstring>
#include<iostream>
#define LL long long
#define INF (2139062143)
#define N (100001)
using namespace std;
int m,n,all,S,T,tot,ans,sum,x;
int f[N],a[N],nxt[N],head[N],cur[N],h[N],co[N];
template <typename T> void read(T&t) {
t=0;
bool fl=true;
char p=getchar();
while (!isdigit(p)) {
if (p=='-') fl=false;
p=getchar();
}
do {
(t*=10)+=p-48;p=getchar();
}while (isdigit(p));
if (!fl) t=-t;
}
inline void add(int x,int y,int z){
a[++tot]=y,nxt[tot]=head[x],head[x]=tot,f[tot]=z;
}
int DFS(int u,int maxflow){
if (u==T) return maxflow;
int used=0;
for (int i=cur[u];~i;i=nxt[i]){
cur[u]=i;
if (f[i]&&h[a[i]]+1==h[u]){
int now=DFS(a[i],min(maxflow-used,f[i]));
used+=now;
f[i]-=now;
f[i^1]+=now;
if (used==maxflow) return used;
}
}
cur[u]=head[u];
if (--co[h[u]]==0) h[S]=all;
h[u]++;
co[h[u]]++;
return used;
}
int main(){
read(m),read(n);
all=m+n+2;
S=m+n+1,T=m+n+2;
tot=1;
memset(head,-1,sizeof(head));
memset(cur,-1,sizeof(cur));
memset(h,0,sizeof(h));
co[0]=all;
for (int i=1;i<=m;i++){
read(x);
sum+=x;
add(S,i,x);
add(i,S,0);
}
for (int i=1;i<=n;i++){
read(x);
add(i+m,T,x);
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);
}
}
while (h[S]<all) ans+=DFS(S,INF);
if (ans<sum){
puts("0");
return 0;
}
puts("1");
for (int i=1;i<=m;i++){
for (int p=head[i];~p;p=nxt[p]){
if (f[p]==0&&a[p]!=S){
printf("%d ",a[p]-m);
}
}
puts("");
}
return 0;
}