网络流24题之圆桌问题
题目描述
假设有来自m 个不同单位的代表参加一次国际会议。每个单位的代表数分别为ri (i =1,2,……,m)。
会议餐厅共有n 张餐桌,每张餐桌可容纳ci (i =1,2,……,n)个代表就餐。
为了使代表们充分交流,希望从同一个单位来的代表不在同一个餐桌就餐。试设计一个算法,给出满足要求的代表就餐方案。
对于给定的代表数和餐桌数以及餐桌容量,编程计算满足要求的代表就餐方案。
输入格式:
第1 行有2 个正整数m 和n,m 表示单位数,n 表示餐桌数,1<=m<=150, 1<=n<=270。
第2 行有m 个正整数,分别表示每个单位的代表数。
第3 行有n 个正整数,分别表示每个餐桌的容量。
输出格式:
如果问题有解,第1 行输出1,否则输出0。接下来的m 行给出每个单位代表的就餐桌号。如果有多个满足要求的方案,只要输出1 个方案。
样例输入:
4 5
4 5 3 5
3 5 2 6 4
样例输出:
1
1 2 4 5
1 2 3 4 5
2 4 5
1 2 3 4 5
本题可以用贪心求解。
首先将桌子从大到小排个序,再讲单位的规模从大到小排个序。单位规模越大就越难满足,所以我们优先考虑单位。
之后先坐大桌子,再坐小桌子就OK了。
但是此题我写的网络流
模型很简单,二分图最大匹配,桌子和单位匹配一下。
建立二分图,每个单位为X集合中的顶点,每个餐桌为Y集合中的顶点,增设附加源S和汇T。
1、从S向每个Xi顶点连接一条容量为该单位人数的有向边。
2、从每个Yi顶点向T连接一条容量为该餐桌容量的有向边。
3、X集合中每个顶点向Y集合中每个顶点连接一条容量为1的有向边。
之后跑最大流。
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
#define N 4000000
int n,m;
int a[N];
int b[N];
int nex[N];
int head[N];
int to[N];
int val[N];
int dep[N];
int S,T;
int idx=1;
void addedge(int a,int b,int c)
{
nex[++idx]=head[a];
head[a]=idx;
to[idx]=b;
val[idx]=c;
}
bool bfs(int S,int T)
{
memset(dep,-1,sizeof(dep));
queue <int > q;
q.push(S);
dep[S]=0;
while(!q.empty())
{
int x=q.front();
q.pop();
for(int i=head[x];i;i=nex[i])
{
if(val[i]&&dep[to[i]]==-1)
{
dep[to[i]]=dep[x]+1;
q.push(to[i]);
if(to[i]==T)
return 1;
}
}
}
return 0;
}
int dinic(int x,int flow)
{
int nowflow=flow;
if(x==T)
return nowflow;
for(int i=head[x];i;i=nex[i])
{
if(val[i]>0&&dep[to[i]]==dep[x]+1)
{
int now=dinic(to[i],min(nowflow,val[i]));
if(now==0)
dep[to[i]]=-1;
nowflow-=now;
val[i]-=now;
val[i^1]+=now;
if(nowflow==0)
break;
}
}
return flow-nowflow;
}
int main()
{
scanf("%d%d",&n,&m);
S=0;
T=n+m+1;
int sum=0;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
sum+=a[i];
addedge(S,i,a[i]);
addedge(i,S,0);
}
for(int i=n+1;i<=m+n;i++)
{
scanf("%d",&b[i]);
addedge(i,T,b[i]);
addedge(T,i,0);
}
for(int i=1;i<=n;i++)
for(int j=n+1;j<=m+n;j++)
{
addedge(i,j,1);
addedge(j,i,0);
}
int ans=0;
while(bfs(S,T))
ans+=dinic(S,1<<30);
if(ans==0||ans<sum)
printf("0");
else
{
puts("1");
for(int i=1;i<=n;i++)
{
for(int j=head[i];j;j=nex[j])
{
if(to[j]!=S&&(!val[j]))
printf("%d ",to[j]-n);
}
puts("");
}
}
}

浙公网安备 33010602011771号