Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 26079 | Accepted: 7872 |
Description
Assume N (N <= 10^5) criminals are currently in Tadu City, numbered from 1 to N. And of course, at least one of them belongs to Gang Dragon, and the same for Gang Snake. You will be given M (M <= 10^5) messages in sequence, which are in the following two kinds:
1. D [a] [b]
where [a] and [b] are the numbers of two criminals, and they belong to different gangs.
2. A [a] [b]
where [a] and [b] are the numbers of two criminals. This requires you to decide whether a and b belong to a same gang.
Input
Output
Sample Input
1 5 5 A 1 2 D 1 2 A 1 2 D 2 4 A 1 4
Sample Output
Not sure yet. In different gangs. In the same gang.
题意:
有T(1到20)个case,每个case开头包含N(1到100000)个人和M(1到100000)条信息。A[x][y]表示要询问x和y是什么关系,关系一共有三种:不能确定,是同伙,是敌人;D[x][y]表示x和y属于不同的团伙。
思路:
首先要弄清楚3种关系到底是怎样的,同伙和敌人很容易理解,但是为什么会有不能确定的关系呢?比如有5个人,1和2是同伙关系,2和3是敌人关系,那么1和3很自然的也是敌人关系了,那么1和4呢?就是不能确定的关系了。说明当集合很多的时候,在没有给出确定关系之前,所有与之未确定的人配对都是不确定关系的。
之前做的都是简单的并查集,直接判断在不在一个集合就行了。可是现在关系有3种,如果还用原来的方法肯定是不行的。所以每当确定一个关系就合并到一个集合中,同时每个元素的权值代表不同的意义,0代表是同伙,1代表是敌人。如果不在一个根节点上的话,就说明关系未确定,属于未确定关系。
这时候的并查集就加上了权值了,权值代表的是与父亲节点的关系,说明父亲节点改变的话,该节点的权值也会发生相应的变化,这时候就要两个方面:路径压缩和合并,因为两者都有父亲节点的变化,说明权值要发生相应的变化。这些变化可以用向量的加减来表示,用root存储每个节点的根节点,用re表示从该节点出发的向量权值,比如:
1.压缩的时候:
比如将C节点连到A的时候,那么就会有条从C到A的向量,那么C到A这条向量的权值就是1+0=1,所以说明B和A是同伙,B和C是敌人,那么则推出A和C是敌人,对应的代码就是re[a]=(re[a]+re[root[a]])%2,%2是为了保证当相加超过2时的情况,这样取出来的结果能保证是0或者1。
2.合并的时候:
当知道A和B是敌人,则A和B之间有条权值为1的边,C和D分别是A和B的根节点,所以要把合并C到D,那么C到D之间的权值就是-re[A]+1+re[B]了;如果是把D合到C则公式是re[A]-1-re[B]了。同时,如果同样为了保证只取到0和1两个值,可以进行+2在%2处理。所以公式为(-re[A]+1+re[B]+2)%2或者(re[A]-1-re[B]+2)%2。这样的话,也可以知道c和d之间的关系了。
3.查询:
当知道两个元素处于同一根节点之后判断是同伙还是敌人,则公式为(re[D]-re[C]+2)%2。如果值为0,说明为同伙,如果是1,说明为敌人。
AC:
#include<stdio.h> #define max 100000+5 int root[max],re[max]; int find(int a) { if(root[a]==a) return a; int r=find(root[a]); re[a]=(re[a]+re[root[a]])%2; return root[a]=r; } //这里的递归写法有点难理解 //先从最低下往上找到根节点 //通过不断返回根节点来进行路径压缩,压缩顺序为根节点往下压缩 //那么权值就为该层权值加上上一层权值 //return root[a]=r相当于root[a]=r;return r; int main() { int n; scanf("%d",&n); while(n--) { int m,t; scanf("%d%d",&m,&t); for(int i=1;i<=m;i++) root[i]=i,re[i]=0; while(t--) { char c; int a,b,fa,fb; scanf(" %c%d%d",&c,&a,&b); fa=find(a); fb=find(b); if(c=='A') { if(fa==fb) { if((re[a]-re[b]+2)%2==0) printf("In the same gang.\n"); else printf("In different gangs.\n"); } else printf("Not sure yet.\n"); } else { if(fa!=fb) { root[fa]=fb; re[fa]=(-re[a]+re[b]+1+2)%2; //这里可以把fa并到fb,也可以把fb并到fa,两者的公式不一样 } } } } return 0; }
总结:
1.带权并查集相当于在树的边上加上了信息,与之前的做法会有所不同;
2.递归的理解有点难理解,顺序有点难搞清,想模拟也不知道如何模拟;
3.fa并到fb与fb并到fa公式是不一样的,但是结果是一样的;
4.巧用向量来理解。
相关推荐
带权并查集(Weighted Union-Find)是一种在数据结构中用于处理不相交集合(Disjoint Set)的算法,它通过合并过程来减少集合的数量,同时考虑合并操作的权重。以下是一个针对带权并查集模板的资源描述: 资源标题...
通过阅读“树形结构-并查集-带权并查集.pdf”,你可以深入了解并查集的原理,学习如何设计和实现带权并查集,以及如何在实际问题中运用这一工具。这份资料将涵盖并查集的基本操作、优化策略以及带权重的合并算法,...
本资源提供了关于最小生成树和并查集的题目列表,共40道题目,涵盖了基础最小生成树、基础并查集、枚举最小生成树、同构图、离线并查集、dfs 枚举组合情况、最大生成树、带权并查集、异或并查集、斯坦纳树、LCA等...
数据结构中的并查集(Disjoint Set)是一种用于处理元素集合的分割问题的数据结构,它主要支持两种操作:合并(union)与查找(find)。在实际应用中,尤其是在算法竞赛(ACM)和图论中,它被广泛用于解决快速查询和...
**并查集**(Union-Find Set)是一种数据结构,用于处理一些不相交集合的合并及查询问题,通常用来解决动态连通性问题。并查集支持两种主要的操作:**并操作**(Union)和**查找操作**(Find)。并操作用于合并两个...
综上所述,"并查集入门学习并查集"的资源可能是针对初学者的教程,通过“并查集.pdf”这个文档,你将能够深入理解并查集的基本概念、操作原理以及如何在实际问题中应用。对于希望提升算法能力,尤其是参与ACM竞赛的...
1、用孩子兄弟表示法表示树并求树的高度和树的度 ...3、find 用折叠规则来实现并查集 使用折叠规则完成一次查找,所需时间比 Find( )函数有所增加,但它能改进树的性能,减少以后查找操作所需的时间。
并查集是一种在图论和算法设计中常用的离散数学结构,主要用于处理一些不相交集合的合并与查询问题。这个压缩包文件“团伙数据”显然包含了一些与并查集算法相关的练习数据和可能的题解,目的是帮助学习者更好地理解...
并查集(Union-Find Sets)是数据结构中一种用于管理元素集合的高效算法,它主要处理两个操作:连接(union)与查找(find)。在并查集中,元素被分到不同的集合中,每个集合代表一个独立的组件。连接操作将两个元素...
并查集的主要操作包括“查找”(Find)和“联合”(Union)。 1. 查找(Find)操作:确定一个元素属于哪个连通分量。通常采用路径压缩的方法,即每次查找过程中,都将当前节点的父节点指向其祖父节点,以减少树的...
并查集是一种在图论和算法设计中常用的离散数学结构,主要用来处理一些不相交集合的合并与查询问题。在本数据压缩包中,主题聚焦于家谱数据,可以推断出这些数据可能包含了家庭成员之间的关系,通过并查集这种数据...
带权并查集是在普通并查集的基础上增加了一个权重的概念,用来表示两个元素之间的关系强度或距离。这种数据结构特别适用于解决包含“相对”信息的问题,即对于任意节点\( c \),有形如 \( f(a,b) = (f(a,c) + f(c,b)...
下面是一个简单的并查集类实现,包含优化后的 `Find` 和 `Union` 方法: ```python class DisjointSet: def __init__(self, items): self.parent = {item: item for item in items} self.rank = {item: 0 for ...
### 并查集模版详解 #### 一、并查集简介 并查集是一种用于处理元素集合的动态数据结构,常被应用于图论、计算机网络、数据挖掘等领域。其核心功能是支持两种操作:合并两个集合(并操作)与查询某个元素所属的...
并查集的主要操作有`Find`和`Union`。 1. **Find**操作:查找元素属于哪个连通分量。通常通过路径压缩(Path Compression)技术优化,使得查找过程的效率提高,每次查询时将沿途经过的节点直接指向其祖父节点,降低...
并查集的核心在于两种操作:查找(find)和合并(union)。查找操作用于确定一个元素所属的集合,而合并操作则是将两个集合合并为一个。在森林的实现方式中,每棵树代表一个集合,树的根节点表示该集合。合并操作...
并查集是一种在图论和算法设计中常用的离散数据结构,主要应用于处理不相交集合的联合与查询问题。在ACM(国际大学生程序设计竞赛)中,它经常被用来解决各种组合优化和图论问题。下面我们将深入探讨并查集的核心...
并查集的核心操作是查找节点的根(Find)以及合并两个集合(Union)。 2. **路径压缩** 为了提高查找效率,通常采用路径压缩技术。即在查找过程中,将沿途经过的节点直接指向上层节点,使得查找过程更快。路径压缩...
并查集是一种在图论和数据结构中广泛使用的算法,主要用来解决网络连通性问题。在这个2010年7月的浙江大学课程设计中,学生们被要求利用并查集来检查网络的连通状态。这是一个典型的离散数学和算法应用的实践任务,...
并查集是一种用于处理集合合并与查询的抽象数据类型,主要应用于解决连通性问题,例如判断图中的两个节点是否在同一连通分量内。在本解题报告中,我们将探讨并查集算法在PKU(北京大学)的三道题目:PKU1182、PKU...