[USACO23OPEN] Custodial Cleanup G

该文章介绍了一个关于无向图的问题,其中每个节点有特定颜色的钥匙。目标是通过操作使得每个房间最终拥有指定颜色的钥匙,并能返回初始节点。解决方案包括使用两次BFS,首先将所有钥匙放置,然后反向模拟取钥匙的过程。若两次BFS均满足条件,则答案为YES,否则为NO。

洛谷[USACO23OPEN] Custodial Cleanup G

题目大意

有一个 n n n个点 m m m条边的无向图,每个房间有一个颜色 C i C_i Ci,以及一把颜色为 S i S_i Si的钥匙。你最初在 1 1 1号节点,手上一把钥匙都没有。

你可以进行任意次以下的操作:

  • 捡起当前房间的钥匙(你可以同时手持多把钥匙)
  • 将部分或全部手上的钥匙放在当前房间(房间内可以同时放多把钥匙)
  • 通过一条边,移到一个相邻的房间,前提是目标房间是房间 1 1 1,或者你拥有至少一个目标房间颜色的钥匙

F F F S S S的一个排列,求能否使每个房间在最后都有一个颜色为 F i F_i Fi的钥匙,且你能回到 1 1 1号节点。

1 ≤ n ≤ 1 0 5 , 0 ≤ m ≤ 1 0 5 , 1 ≤ C i , S i , F i ≤ n 1\leq n\leq 10^5,0\leq m\leq 10^5,1\leq C_i,S_i,F_i\leq n 1n105,0m105,1Ci,Si,Fin


题解

首先,我们可以先将所有的钥匙都拿出来,在对应放入每一个房间。用 B F S BFS BFS模拟一次,用 v e c t o r vector vector存储那些相邻但没有对应颜色的节点,在拿到对应颜色的钥匙时再加入队列。当然,如果有一些点不能达到,但这些点的 S i S_i Si F i F_i Fi相同,那也是可行的;但如果存在一些点不能达到且 S i S_i Si F i F_i Fi不同那么答案就是 N O NO NO

然后,我们看看怎么放钥匙。因为直接放比较难处理,而且题目要求最终返回 1 1 1号节点,所以我们可以倒过来做,那这就变成了一个“取钥匙”的过程。因为在上面取完钥匙后经过的点都可以到达,所以现在的“取钥匙”也可以到达这些点。当然,上面取钥匙时达不到的点在现在“取钥匙”时也不可以进入。

第二次“取钥匙”的 B F S BFS BFS和第一次的比较相似, 但还是有一点差异。因为在放完钥匙出来后并不需要还有原来这个房间的颜色的钥匙,所以倒过来的“取钥匙”中,进入一个节点的条件可以为你当前有对应颜色的钥匙,也可以为这个节点的 C i C_i Ci F i F_i Fi相等。

如果第一次 B F S BFS BFS后存在不能达到的且 C i ≠ F i C_i\neq F_i Ci=Fi的点,或者第二次存在不能达到的且第一次能达到的点,则答案为 N O NO NO;否则答案为 Y E S YES YES

时间复杂度为 O ( n + m ) O(n+m) O(n+m)

code

#include<bits/stdc++.h>
using namespace std;
int tq,n,m,x,y,tot,d[500005],l[500005],r[500005];
int c[100005],v1[100005],v2[100005],z[100005],cm[100005],no[100005],hv[100005];
queue<int>q;
vector<int>w[100005];
void add(int xx,int yy){
	l[++tot]=r[xx];d[tot]=yy;r[xx]=tot;
}
bool pd1(){
	for(int i=1;i<=n;i++){
		z[i]=cm[i]=hv[i]=no[i]=0;
		w[i].clear();
	}
	q.push(1);z[1]=1;
	while(!q.empty()){
		int u=q.front();q.pop();
		cm[u]=1;
		++hv[v1[u]];
		if(hv[v1[u]]==1){
			for(int i=0;i<w[v1[u]].size();i++){
				q.push(w[v1[u]][i]);
			}
		}
		for(int i=r[u];i;i=l[i]){
			if(!z[d[i]]){
				z[d[i]]=1;
				if(hv[c[d[i]]]) q.push(d[i]);
				else w[c[d[i]]].push_back(d[i]);
			}
		}
	}
	for(int i=1;i<=n;i++){
		if(!cm[i]){
			if(v1[i]==v2[i]) no[i]=1;
			else return 0;
		}
	}
	return 1;
}
bool pd2(){
	for(int i=1;i<=n;i++){
		z[i]=cm[i]=hv[i]=0;
		w[i].clear();
	}
	q.push(1);z[1]=1;
	while(!q.empty()){
		int u=q.front();q.pop();
		cm[u]=1;
		++hv[v2[u]];
		if(hv[v2[u]]==1){
			for(int i=0;i<w[v2[u]].size();i++){
				q.push(w[v2[u]][i]);
			}
		}
		for(int i=r[u];i;i=l[i]){
			if(!no[d[i]]&&!z[d[i]]){
				z[d[i]]=1;
				if(hv[c[d[i]]]||v2[d[i]]==c[d[i]]) q.push(d[i]);
				else w[c[d[i]]].push_back(d[i]);
			}
		}
	}
	for(int i=1;i<=n;i++){
		if(!cm[i]&&!no[i]) return 0;
	}
	return 1;
}
int main()
{
	scanf("%d",&tq);
	while(tq--){
		scanf("%d%d",&n,&m);
		for(int i=1;i<=n;i++) scanf("%d",&c[i]);
		for(int i=1;i<=n;i++) scanf("%d",&v1[i]);
		for(int i=1;i<=n;i++) scanf("%d",&v2[i]);
		for(int i=1;i<=m;i++){
			scanf("%d%d",&x,&y);
			add(x,y);add(y,x);
		}
		if(pd1()&&pd2()) printf("YES\n");
		else printf("NO\n");
		tot=0;
		for(int i=1;i<=n;i++){
			r[i]=c[i]=v1[i]=v2[i]=0;
		}
	}
	return 0;
}
【SCI级别】多策略改进鲸鱼优化算法(HHWOA)和鲸鱼优化算法(WOA)在CEC2017测试集函数F1-F30寻优对比内容概要:本文档主要介绍了一项关于多策略改进鲸鱼优化算法(HHWOA)与标准鲸鱼优化算法(WOA)在CEC2017测试集函数F1-F30上进行寻优性能对比的研究,属于智能优化算法领域的高水平科研工作。文中通过Matlab代码实现算法仿真,重点展示了HHWOA在收敛速度、寻优精度和稳定性方面的优势,体现了多策略改进的有效性。该研究适用于复杂优化问题求解,尤其在工程优化、参数辨识、机器学习超参数调优等领域具有应用潜力。; 适合人群:具备一定算法基础和Matlab编程能力的研究生、科研人员及从事智能优化算法开发与应用的工程技术人员,尤其适合致力于SCI论文写作与算法创新的研究者。; 使用场景及目标:①用于理解鲸鱼优化算法的基本原理及多策略改进思路(如种群初始化、非线性收敛因子、精英反向学习等);②为智能优化算法的性能测试与对比实验提供CEC2017标准测试平台的实现参考;③支撑学术研究中的算法创新与论文复现工作。; 阅读建议:建议结合提供的Matlab代码进行实践操作,重点关注HHWOA的改进策略模块与WOA的差异,通过重复实验验证算法性能,并可将其思想迁移至其他优化算法的改进中,提升科研创新能力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值