P3254 圆桌问题

P3254 圆桌问题

题目描述

假设有来自m 个不同单位的代表参加一次国际会议。每个单位的代表数分别为(ri (i =1,2,……,m))

会议餐厅共有(n)张餐桌,每张餐桌可容纳(ci (i =1,2,……,n))个代表就餐。

为了使代表们充分交流,希望从同一个单位来的代表不在同一个餐桌就餐。试设计一个算法,给出满足要求的代表就餐方案。

对于给定的代表数和餐桌数以及餐桌容量,编程计算满足要求的代表就餐方案。


典型的二分图匹配

很显然,任何一个公司的人都可以随便坐。而一个公司的人不能有超过一个人在同一张桌子上。

每个桌子和公司看做一个点,然后每每相连一条流量为一的边

然后我们要所有人都坐上。就是要满流

然后跑一边dinic就行了

#include<cstdio> 
#include<algorithm>
#include<iostream>
#include<cstring>
#include<queue>
using std::queue;
using std::min;
const int inf=0x7fffffff;
const int maxn=10000;
struct node
{
	int p;
	int f;
	int nxt;
};
node line[maxn<<3];
int head[maxn],tail=-1;
int cur[maxn];
int dis[maxn];
void add(int a,int b,int c)
{
	line[++tail].p=b;
	line[tail].f=c;
	line[tail].nxt=head[a];
	head[a]=tail;
}
bool bfs(int begin,int end)
{
	memset(dis,0,sizeof(dis));
	dis[begin]=1;
	queue<int>q;
	q.push(begin);
	while(!q.empty())
	{
		int pas=q.front();q.pop();
		for(int i=head[pas];i!=-1;i=line[i].nxt)
			if(!dis[line[i].p]&&line[i].f)
			{
				dis[line[i].p]=dis[pas]+1;
				q.push(line[i].p);
			}
	}
	return dis[end];
}
int dfs(int now,int aim,int flow)
{
	if(now==aim||!flow)	return flow;
	int res=0,f;
	for(int &i=cur[now];i!=-1;i=line[i].nxt)
		if(dis[line[i].p]==dis[now]+1&&(f=dfs(line[i].p,aim,min(flow,line[i].f))))
		{
			flow-=f;
			res+=f;
			line[i].f-=f;
			line[i^1].f+=f;
			if(!flow) break;
		}
	return res;
} 
int dinic(int begin,int end,int t)
{
	int res=0;
	while(bfs(begin,end))
	{
		for(int i=0;i<=t;i++)
			cur[i]=head[i];
		res+=dfs(begin,end,inf);
	}
	return res;
}
int main()
{
	memset(head,-1,sizeof(head));
	int n,m;
	scanf("%d%d",&n,&m);
	int a,tot=0;
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&a);
		add(0,i,a);
		add(i,0,0);
		tot+=a;
	}
	for(int i=1;i<=m;i++)
	{
		scanf("%d",&a);
		add(n+i,n+m+1,a);
		add(n+m+1,n+i,0);
	}
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
			add(i,n+j,1),add(n+j,i,0);
	int judge=dinic(0,n+m+1,n+m+1);
	if(judge!=tot)
	{
		printf("0");
		return 0;
	}
	printf("1
");
	for(int i=1;i<=n;i++)
	{
		for(int j=head[i];j!=-1;j=line[j].nxt)
			if(!line[j].f&&line[j].p)
				printf("%d ",line[j].p-n);
		printf("
");
	}
	return 0;
}
原文地址:https://www.cnblogs.com/Lance1ot/p/9501789.html