1. 程式人生 > >[網絡流24題]圓桌問題

[網絡流24題]圓桌問題

== pop fine bsp 思路 class set head def

題目:洛谷P3254。

題目大意:
有n個單位和m張桌子,每個單位有一定的人數,每張桌子也有一定的容量。一張桌子上不能有兩個同一單位的人。現在問你能否坐下,若能則輸出一種方案。
解題思路:
最大流。
從S向每個單位連一條容量為(單位人數)的邊,代表這個單位有那麽多人。
從每張桌子向T連一條容量為(桌子容量)的邊,代表這張桌子能做那麽多人。
從每個單位向每張桌子連一條容量為1的邊,代表每個單位在一張桌子上只能坐一個人。
然後若最大流量不等於總人數,則無解。否則有解。
輸出方案,就枚舉邊,對於一條從單位流向桌子的邊,若跑完剩余容量為0,則該單位在這張桌子上坐了人。

C++ Code:

#include<bits/stdc++.h>
#define S 0
#define T 1000
struct edge{
	int from,to,cap,nxt;
}e[200000];
inline int readint(){
	int c=getchar(),d=0;
	for(;!isdigit(c);c=getchar());
	for(;isdigit(c);c=getchar())
	d=(d<<3)+(d<<1)+(c^‘0‘);
	return d;
}
int cnt=1,n,m,head[1005],s=0,level[1005],iter[1005];
std::vector<int>v[300]; 
inline int addedge(const int u,const int v,const int t){
	e[++cnt]=(edge){u,v,t,head[u]};
	head[u]=cnt;
	e[++cnt]=(edge){v,u,0,head[v]};
	head[v]=cnt;
}
std::queue<int>q;
inline int min(const int a,const int b){return a<b?a:b;}
void bfs(){
	q.push(S);
	level[S]=1;
	while(!q.empty()){
		int u=q.front();q.pop();
		for(int i=head[u];~i;i=e[i].nxt)
		if(e[i].cap&&!~level[e[i].to]){
			level[e[i].to]=level[u]+1;
			q.push(e[i].to);
		}
	}
}
int dfs(const int u,const int f){
	if(!f||u==T)return f;
	for(int& i=iter[u];~i;i=e[i].nxt)
	if(e[i].cap&&level[e[i].to]>level[u]){
		int d=dfs(e[i].to,min(f,e[i].cap));
		if(d){
			e[i].cap-=d;
			e[i^1].cap+=d;
			return d;
		}
	}
	return 0;
}
int dinic(){
	for(int flow=0,f;;){
		memset(level,-1,sizeof level);
		if(bfs(),!~level[T])return flow;
		memcpy(iter,head,sizeof head);
		while(f=dfs(S,0x3f3f3f3f))flow+=f;
	}
}
int main(){
	memset(head,-1,sizeof head);
	n=readint(),m=readint();
	for(int i=1;i<=n;++i){
		int p=readint();
		s+=p;
		addedge(S,i,p);
	}
	for(int i=1;i<=m;++i)addedge(n+i,T,readint());
	for(int i=1;i<=n;++i)
	for(int j=1;j<=m;++j)
	addedge(i,n+j,1);
	if(dinic()!=s)return puts("0"),0;
	puts("1");
	for(int i=1;i<=cnt;++i)
	if(e[i].from<=n&&e[i].from&&e[i].to>n&&e[i].to<=n+m&&!e[i].cap)v[e[i].from].push_back(e[i].to-n);
	for(int i=1;i<=n;++i)
	if(v[i].size()){
		for(int j=v[i].size()-1;j>0;--j)printf("%d ",v[i][j]);
		printf("%d\n",v[i][0]);
	}else putchar(‘\n‘);
	return 0;
}

[網絡流24題]圓桌問題