【网络流】POJ1149 PIGS

本文探讨了一个有趣的问题:如何通过构建最大流图解决猪圈买卖中顾客购买数量最大化的难题。文章详细介绍了如何将顾客的选择和猪圈间的调换抽象为图论中的节点与边,最终利用Dinic算法求解最大流。

题目大意:有 m 个猪圈,每个猪圈里初始时有若干头猪。一开始所有猪圈都是关闭的。依次来了 n 个顾客,每个顾客分别会打开指定的几个猪圈,从中买若干头猪。每个顾客分别都有他能够买的数量的上限。每个顾客走后,他打开的那些猪圈中的猪,都可以被任意地调换到其它开着的猪圈里,然后所有猪圈重新关上。问总共最多能卖出多少头猪。

建图是个难点。我们考虑当一个顾客打开若干个猪圈时,这些猪圈可以看做是被合并为了一个点,因为它们之间可以相互调换。而当后面的人再次选到被开过的猪圈时,就相当于他选了与这个猪圈一起被选的猪圈。举个离子吧:

比如第一个人来,选了①号和②号猪圈。第二个人来,选了第②号猪圈和第③号猪圈。

由于第一个人选了①号和②号,那么①号和②号是可以相互调换的,第二个人选②号的时候就相当于同时选了①号和②号。

【因为可以把①号的猪转到②号,第二个人就能同时取到这两个地方的猪】

第二个人的③号没有被选过,那么他选的③号就只是③号。

下面是一个建图的例子:

【后面是选的猪圈的序号】

第一个人:①②;第二个人:②③;

第三个人:④⑤;第四个人:②⑤;

首先从源点向每个猪圈连一条边,容量为猪的数量。

【我们可以把每一个顾客看做是一个合并后的点,因为每来一个顾客,我们就可以把他所开过的猪圈合并。】

当第一个顾客来时,①和②向第一个人连一条边【把①和②合并】容量∞,然后第一个人向汇点连一条边,容量为这个人最多能买多少猪。

第二个人来时,他的②相当于①和②,那么从第一个顾客连一条边过来就相当于是合并了。

第三个人来时,④和⑤都没有被合并过,直接连过来就行了。

第四个人来时,②跟①合并过,又和③合并过,那么②代表的就是①②③这三个猪圈,我们选它最晚的合并的点就行了。

【第一个人合并了②,第二个人也合并了②,那么选第二个人来合并,因为第二个人合并了更多的点】

这样,图就建好了,如下:

下面是代码:

#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int oo=1<<30;
const int maxn=10010;
int cnt=1,Head[maxn],Next[maxn<<1],W[maxn<<1],V[maxn<<1],depth[maxn];
int last[maxn],n,m,lim,num,k,s,t;
void Add(int u,int v,int w){
	++cnt;
	Next[cnt]=Head[u];
	V[cnt]=v;
	W[cnt]=w;
	Head[u]=cnt;
}
void addedge(int u,int v,int w){Add(u,v,w),Add(v,u,0);}
int bfs(){
	memset(depth,0,sizeof(depth));
	queue<int> Q;
	depth[s]=1;
	Q.push(s);
	while(!Q.empty()){
		int u=Q.front();
		Q.pop();
		for(int i=Head[u];i;i=Next[i]){
			if(W[i]>0&&depth[V[i]]==0){
				depth[V[i]]=depth[u]+1;
				Q.push(V[i]);
			}
		}
	}
	return depth[t];
}
int dfs(int u,int dist){
	if(u==t) return dist;
	for(int i=Head[u];i;i=Next[i]){
		if(depth[V[i]]==depth[u]+1&&W[i]){
			int di=dfs(V[i],min(W[i],dist));
			if(di>0){
				W[i]-=di;
				W[i^1]+=di;
				return di;
			}
		}
	}
	return 0;
}
int dinic(){
	int ans=0;
	while(bfs()){
		while(int D=dfs(s,oo))
			ans+=D;
	}
	return ans;
}
void read(int &x){x=0;char ch=getchar();while(ch>'9'||ch<'0') ch=getchar();while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();}
int main(){
	read(m),read(n),s=0,t=m+n+1;
	for(int i=1;i<=m;++i){
		read(k);
		addedge(s,i,k);
		last[i]=i;
	}
	for(int i=1;i<=n;++i){
		read(num);
		for(int j=1;j<=num;++j){
			read(k);
			if(last[k]!=i+m)
			addedge(last[k],i+m,oo);
			last[k]=i+m;
		}
		read(lim);
		addedge(i+m,t,lim);
	}
	printf("%d\n",dinic());
}
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;const int oo=1<<30;const int maxn=10010;int cnt=1,Head[maxn],Next[maxn<<1],W[maxn<<1],V[maxn<<1],depth[maxn],last[maxn],n,m,lim,num,k,s,t;void Add(int u,int v,int w){++cnt;Next[cnt]=Head[u];V[cnt]=v;W[cnt]=w;Head[u]=cnt;}void addedge(int u,int v,int w){Add(u,v,w),Add(v,u,0);}int bfs(){memset(depth,0,sizeof(depth));queue<int> Q;depth[s]=1;Q.push(s);while(!Q.empty()){int u=Q.front();Q.pop();for(int i=Head[u];i;i=Next[i]){if(W[i]>0&&depth[V[i]]==0){depth[V[i]]=depth[u]+1;Q.push(V[i]);}}}return depth[t];}int dfs(int u,int dist){if(u==t) return dist;for(int i=Head[u];i;i=Next[i]){if(depth[V[i]]==depth[u]+1&&W[i]){int di=dfs(V[i],min(W[i],dist));if(di>0){W[i]-=di;W[i^1]+=di;return di;}}}return 0;}int dinic(){int ans=0;while(bfs()){while(int D=dfs(s,oo))ans+=D;}return ans;}void read(int &x){x=0;char ch=getchar();while(ch>'9'||ch<'0') ch=getchar();while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();}int main(){read(m),read(n),s=0,t=m+n+1;for(int i=1;i<=m;++i){read(k);addedge(s,i,k);last[i]=i;}for(int i=1;i<=n;++i){read(num);for(int j=1;j<=num;++j){read(k);if(last[k]!=i+m)addedge(last[k],i+m,oo);last[k]=i+m;}read(lim);addedge(i+m,t,lim);}printf("%d\n",dinic());}

 

基于径向基函数神经网络RBFNN的自适应滑模控制学习(Matlab代码实现)内容概要:本文介绍了基于径向基函数神经网络(RBFNN)的自适应滑模控制方法,并提供了相应的Matlab代码实现。该方法结合了RBF神经网络的非线性逼近能力和滑模控制的强鲁棒性,用于解决复杂系统的控制问题,尤其适用于存在不确定性和外部干扰的动态系统。文中详细阐述了控制算法的设计思路、RBFNN的结构与权重更新机制、滑模面的构建以及自适应律的推导过程,并通过Matlab仿真验证了所提方法的有效性和稳定性。此外,文档还列举了大量相关的科研方向和技术应用,涵盖智能优化算法、机器学习、电力系统、路径规划等多个领域,展示了该技术的广泛应用前景。; 适合人群:具备定自动控制理论基础和Matlab编程能力的研究生、科研人员及工程技术人员,特别是从事智能控制、非线性系统控制及相关领域的研究人员; 使用场景及目标:①学习和掌握RBF神经网络与滑模控制相结合的自适应控制策略设计方法;②应用于电机控制、机器人轨迹跟踪、电力电子系统等存在模型不确定性或外界扰动的实际控制系统中,提升控制精度与鲁棒性; 阅读建议:建议读者结合提供的Matlab代码进行仿真实践,深入理解算法实现细节,同时可参考文中提及的相关技术方向拓展研究思路,注重理论分析与仿真验证相结合。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值