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;
}

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