LOJ #6004. 「网络流 24 题」圆桌聚餐

题意:假设有来自 mm 个不同单位的代表参加一次国际会议。每个单位的代表数分别为 rir_i。会议餐厅共有 nn 张餐桌,每张餐桌可容纳 cic_i个代表就餐。
为了使代表们充分交流,希望从同一个单位来的代表不在同一个餐桌就餐。
试设计一个算法,给出满足要求的代表就餐方案。

连出这样一个图跑最大流即可。
左部点为单位,右部点为餐桌。
一个单位至多一个人去某个餐桌。(所以容量为1)
如果S相连的边的容量都没了就合法。

#include<map>
#include<queue>
#include<cmath>
#include<bitset>
#include<cstdio>
#include<vector>
#include<cctype>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define fi first
#define se second
#define lc (x<<1)
#define rc (x<<1|1)
#define g getchar()
#define mk make_pair
#define pi pair<int,int>
#define pb push_back
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int N=433,inf=2e9;
template<class o>void qr(o&x) {
	char c=g;int f=1;x=0;
	while(!isdigit(c)){if(c=='-')f=-1;c=g;}
	while(isdigit(c))x=x*10+c-'0',c=g;
	x*=f;
}
template<class o>void qw(o x) {
	if(x/10)qw(x/10);
	putchar(x%10+'0');
}
template<class o> void pr1(o x) {
	if(x<0)x=-x,putchar('-');
	qw(x); putchar(' ');
}
template<class o>void pr2(o x) {
	if(x<0)x=-x,putchar('-');
	qw(x);puts("");
}

int n,m,d[N],st,ed,q[N],tot;
struct edge{int y,next,c;} a[N*N]; int len=1,last[N],cur[N];
void ins(int x,int y,int z) {a[++len]=(edge){y,last[x],z}; last[x]=len;}
void add(int x,int y,int z) {ins(x,y,z); ins(y,x,0);}

bool bfs() {
	memset(d,0,ed+1<<2);
	int l,r; q[l=r=1]=st; d[st]=1;
	while(l<=r) {
		int x=q[l++];
		for(int k=last[x],y;k;k=a[k].next)
			if(a[k].c&&!d[y=a[k].y]) {
				d[y]=d[x]+1;
				q[++r]=y;
				if(y==ed) return 1;
			}
	}
	return 0;
}

int dfs(int x,int f) {
	if(x==ed) return f;
	int s=0,t;
	for(int k=cur[x],y,z;k&&s<f;k=a[k].next) {
		y=a[k].y; z=a[k].c;
		if(z>0&&d[y]==d[x]+1) {
			s+=(t=dfs(y,min(f-s,z)));
			a[k].c-=t; a[k^1].c+=t;
			cur[x]=k;
		}
	}
	if(!s) d[x]=0;
	return s;
}

int main() {
	qr(n); qr(m); st=0; ed=n+m+1;
	for(int i=1,x;i<=n;i++) qr(x),add(st,i,x),tot+=x;
	for(int i=1,x;i<=m;i++) qr(x),add(i+n,ed,x);
	for(int i=1;i<=n;i++)
		for(int j=n+1;j<=n+m;j++) add(i,j,1);
	while(bfs()) memcpy(cur,last,ed+1<<2),tot-=dfs(st,inf);
	if(!tot) puts("1");
	else return puts("0"),0;
	for(int i=1;i<=n;i++) {
		for(int k=last[i],y;k;k=a[k].next) {
			y=a[k].y;
			if(y&&!a[k].c) pr1(y-n);
		}
		puts("");
	}
	return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章