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

相关文章

好题——hdu2522(小数问题:求1/n的第一个循环节)

好喜欢这题,第一次做小数问题,一开始真心没思路,然后参考了网上的一些资料。 知识点***********************************无限不循环小数即无理数,不能写作两整数之比*****************************(一开始没想到,小学没学好) 此题1/n肯定是一个有限循环小数,了解这些后就能做此题了。 按照除法的机制,用一个函数表示出来就可以了,代码如下

poj 1182 并查集 食物链类

题意: 有n只动物,分别编号1....n。所有动物都属于A,B,C中的一种,已知A吃B,B吃C,C吃A。 按顺序给出下面两种共K条信息: 1. x 和 y 属于同一类。 2. x 吃 y 。 然而这些信息可能会出错,有可能有的信息和之前给出的信息矛盾,也有的信息可能给出的 x 和 y 不在n的范围内。 求k条信息中有多少条是不正确的。 解析: 对于每只动物,创建3个元素 i

POJ1269 判断2条直线的位置关系

题目大意:给两个点能够确定一条直线,题目给出两条直线(由4个点确定),要求判断出这两条直线的关系:平行,同线,相交。如果相交还要求出交点坐标。 解题思路: 先判断两条直线p1p2, q1q2是否共线, 如果不是,再判断 直线 是否平行, 如果还不是, 则两直线相交。  判断共线:  p1p2q1 共线 且 p1p2q2 共线 ,共线用叉乘为 0  来判断,  判断 平行:  p1p

pip-tools:打造可重复、可控的 Python 开发环境,解决依赖关系,让代码更稳定

在 Python 开发中,管理依赖关系是一项繁琐且容易出错的任务。手动更新依赖版本、处理冲突、确保一致性等等,都可能让开发者感到头疼。而 pip-tools 为开发者提供了一套稳定可靠的解决方案。 什么是 pip-tools? pip-tools 是一组命令行工具,旨在简化 Python 依赖关系的管理,确保项目环境的稳定性和可重复性。它主要包含两个核心工具:pip-compile 和 pip

poj3750约瑟夫环,循环队列

Description 有N个小孩围成一圈,给他们从1开始依次编号,现指定从第W个开始报数,报到第S个时,该小孩出列,然后从下一个小孩开始报数,仍是报到S个出列,如此重复下去,直到所有的小孩都出列(总人数不足S个时将循环报数),求小孩出列的顺序。 Input 第一行输入小孩的人数N(N<=64) 接下来每行输入一个小孩的名字(人名不超过15个字符) 最后一行输入W,S (W < N),用

POJ1988带权并查集

M u v 将u所在的堆移动到v所在的堆的上面 C u 求u的下面有多少块 带权并查集 import java.io.BufferedReader;import java.io.InputStream;import java.io.InputStreamReader;import java.io.PrintWriter;import java.math.BigInteger;i

POJ1703带权并查集

D: u v  u与v在不同的集合 A: u v  查询u与v的关系 1)压缩路径过程        fu->root   0  1  u-fu 0                 0  1   1                 1  0 2)合并过程 fu->fv      u->fu   0 1   v->fv 0            1 0 1            0

校验码:奇偶校验,CRC循环冗余校验,海明校验码

文章目录 奇偶校验码CRC循环冗余校验码海明校验码 奇偶校验码 码距:任何一种编码都由许多码字构成,任意两个码字之间最少变化的二进制位数就称为数据检验码的码距。 奇偶校验码的编码方法是:由若干位有效信息(如一个字节),再加上一个二进制位(校验位)组成校验码。 奇校验:整个校验码中1的个数为奇数 偶校验:整个校验码中1的个数为偶数 奇偶校验,可检测1位(奇数位)的错误,不可纠错。

react笔记 8-17 属性绑定 class绑定 引入图片 循环遍历

1、绑定属性 constructor(){super()this.state={name:"张三",title:'我是一个title'}}render() {return (<div><div>aaaaaaa{this.state.name}<div title={this.state.title}>我是一个title</div></div></div>)} 绑定属性直接使用花括号{}   注

读软件设计的要素04概念的关系

1. 概念的关系 1.1. 概念是独立的,彼此间无须相互依赖 1.1.1. 一个概念是应该独立地被理解、设计和实现的 1.1.2. 独立性是概念的简单性和可重用性的关键 1.2. 软件存在依赖性 1.2.1. 不是说一个概念需要依赖另一个概念才能正确运行 1.2.2. 只有当一个概念存在时,包含另一个概念才有意义 1.3. 概念依赖关系图简要概括了软件的概念和概念存在的理