P2024 [NOI2001] 食物链 带权并查集 循环关系

2024-02-18 01:52

本文主要是介绍P2024 [NOI2001] 食物链 带权并查集 循环关系,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

题目: 

P2024 [NOI2001] 食物链 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 

本文学习自: 

题解 P2024 【食物链】 - RE: 从零开始的异世界信竞生活 - 洛谷博客 (luogu.com.cn) 

————

关系并查集其实就是在普通并查集的基础上额外开个数组re,用来表示每个点与其根节点的关系。

这个其实很好理解。设0为同类,1为该点吃根节点,2为根节点吃该点。 

难处理的就是合并,以及压缩并查集时,re关系数组如何处理。

只需理解这个图:

 

为什么有这个等式,其实这个等式左右两边表示的都是A与F2的关系 。(A到F2的两条路径和)

再结合关系是循环的(A吃B,B吃C,C吃D,那么A和D就是同类,构成循环了)。

然后就是注意,减法可能减负的,可以加个模数再取模。

代码: 

两个find,第一个是压缩时,循环处理re关系数组

第二个注释掉的是递归法,回溯的时候处理re关系数组

int fa[50005];
//带权并查集
int rela[50005];void init(int _size)
{for (int i = 0; i <= _size; i++)fa[i] = i;
}
int find(int aim)
{int cur = aim;int sum = 0;while (fa[aim] != aim){sum += rela[aim];//存aim = fa[aim];}while (fa[cur] != cur){int tmp = cur;cur = fa[cur];fa[tmp] = aim;sum -= rela[tmp];rela[tmp] = (sum+rela[tmp]) % 3;}return aim;
}
//int find(int aim)//从根往下更新
//{
//	int father = fa[aim];
//	if (fa[aim] == aim)
//		return aim;
//	fa[aim] = find(father);
//	rela[aim] = (rela[aim] + rela[father]) % 3;
//	return fa[aim];
//}
void join(int a, int b,int op)
{int oa = a, ob = b;a = find(a);b = find(b);fa[a] = b;rela[a] = (op + rela[ob] - rela[oa]+3)%3;//只处理祖先就好了,其余在压缩的时候处理//并查集就是合并根
}void solve()
{int n, k;cin >> n >> k;init(n);int op, a, b;int ans = 0;for (int i = 1; i <= k; i++){cin >> op >> a >> b;if (a > n || b > n){ans++;continue;}if (op == 1){if (find(a) == find(b)){if(rela[a] != rela[b])ans++;			}else{join(a, b,0);}}else{if (a == b){ans++;continue;}//如果在一个集合中,要判断关系是否正确if (find(a) == find(b)){if (rela[a] != (1 + rela[b]) % 3){ans++;}}elsejoin(a, b,1);}}cout << ans << endl;
}
signed main()
{ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);int t = 1;//cin >> t;while (t--){solve();}return 0;
}

这篇关于P2024 [NOI2001] 食物链 带权并查集 循环关系的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/719673

相关文章

java中新生代和老生代的关系说明

《java中新生代和老生代的关系说明》:本文主要介绍java中新生代和老生代的关系说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、内存区域划分新生代老年代二、对象生命周期与晋升流程三、新生代与老年代的协作机制1. 跨代引用处理2. 动态年龄判定3. 空间分

Java中的for循环高级用法

《Java中的for循环高级用法》本文系统解析Java中传统、增强型for循环、StreamAPI及并行流的实现原理与性能差异,并通过大量代码示例展示实际开发中的最佳实践,感兴趣的朋友一起看看吧... 目录前言一、基础篇:传统for循环1.1 标准语法结构1.2 典型应用场景二、进阶篇:增强型for循环2.

Python循环结构全面解析

《Python循环结构全面解析》循环中的代码会执行特定的次数,或者是执行到特定条件成立时结束循环,或者是针对某一集合中的所有项目都执行一次,这篇文章给大家介绍Python循环结构解析,感兴趣的朋友跟随... 目录for-in循环while循环循环控制语句break语句continue语句else子句嵌套的循

MySQL存储过程之循环遍历查询的结果集详解

《MySQL存储过程之循环遍历查询的结果集详解》:本文主要介绍MySQL存储过程之循环遍历查询的结果集,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录前言1. 表结构2. 存储过程3. 关于存储过程的SQL补充总结前言近来碰到这样一个问题:在生产上导入的数据发现

Nginx部署React项目时重定向循环问题的解决方案

《Nginx部署React项目时重定向循环问题的解决方案》Nginx在处理React项目请求时出现重定向循环,通常是由于`try_files`配置错误或`root`路径配置不当导致的,本文给大家详细介... 目录问题原因1. try_files 配置错误2. root 路径错误解决方法1. 检查 try_f

Spring三级缓存解决循环依赖的解析过程

《Spring三级缓存解决循环依赖的解析过程》:本文主要介绍Spring三级缓存解决循环依赖的解析过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、循环依赖场景二、三级缓存定义三、解决流程(以ServiceA和ServiceB为例)四、关键机制详解五、设计约

Spring 中的循环引用问题解决方法

《Spring中的循环引用问题解决方法》:本文主要介绍Spring中的循环引用问题解决方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录什么是循环引用?循环依赖三级缓存解决循环依赖二级缓存三级缓存本章来聊聊Spring 中的循环引用问题该如何解决。这里聊

C# foreach 循环中获取索引的实现方式

《C#foreach循环中获取索引的实现方式》:本文主要介绍C#foreach循环中获取索引的实现方式,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录一、手动维护索引变量二、LINQ Select + 元组解构三、扩展方法封装索引四、使用 for 循环替代

Spring Boot循环依赖原理、解决方案与最佳实践(全解析)

《SpringBoot循环依赖原理、解决方案与最佳实践(全解析)》循环依赖指两个或多个Bean相互直接或间接引用,形成闭环依赖关系,:本文主要介绍SpringBoot循环依赖原理、解决方案与最... 目录一、循环依赖的本质与危害1.1 什么是循环依赖?1.2 核心危害二、Spring的三级缓存机制2.1 三

springboot循环依赖问题案例代码及解决办法

《springboot循环依赖问题案例代码及解决办法》在SpringBoot中,如果两个或多个Bean之间存在循环依赖(即BeanA依赖BeanB,而BeanB又依赖BeanA),会导致Spring的... 目录1. 什么是循环依赖?2. 循环依赖的场景案例3. 解决循环依赖的常见方法方法 1:使用 @La