并查集 专辑 之 虚空节点之谜

在并查集问题的处理中有几种常见的实用方法,下面介绍第一种:虚空节点(我这么叫,莫黑)。

结合例题身体好~

洛谷oj  10.19比赛题目  宗教信仰 religion

题目描述 Description
在一片大陆上有许多个国家和许多个宗教。每一个国家在某一时刻仅有1个官方信仰的宗教。
这些宗教可能会互相兼并,合成一个宗教。某个国家也可能在某一时刻改信一个宗教。
现在给出宗教兼并和国家改宗的大事表,以及若干个询问,询问在当前时刻2个国家是否信仰一个宗教。
每个国家在开始时,都信仰着不同的宗教。
 输入输出格式 Input/output
输入格式:
第一行 1 个整数 N 表示国家数量。
第二行 1 个整数 Q 表示一共有Q个大事及询问。
以下 Q 行 每行形式如下:
1 A B   表示 A 国所信仰的宗教与 B 国所信仰的宗教 合并为 1 个宗教;
2 A B   表示 A 国改为信仰 B 国所信仰的宗教;
3 A B   表示查询 A 国 和 B 国 现在是否信仰同一个宗教;
//如果 1 2 3信仰A宗教,4 5信仰B宗教,那么执行2 1 4 后,2 3国信仰A宗教,1 4 5国信
//仰B宗教
输出格式:
对于每一个 询问 输出 ‘Yes‘ 或 ‘No‘ 来回答询问,分别表示是同一个宗教或不是同一个宗教.
input
5
6
1 3 4
1 2 4
3 2 4
2 5 2
3 1 5
3 3 5
output
Yes
No
Yes

题目链接:http://www.luogu.org/problem/show?pid=T105

好了,分析一下,显然是并查集对吧,那么 3操作是查询,1操作路径压缩合并,2吗,是什么呢。。。。。。

我们很快会想到:如果只改这么一个点的话,那么如果这是个根(老祖宗,路径压缩后的根节点),那么我一改,岂不难办了?

这样好了,我们每一个点刚开始的时候都把他父亲设成一个根本不存在的点好了~~这样一来原来的根就变成了现在我们的某虚空节点的一个儿子了,只要合并的时候只把虚空节点的儿子接到别处就好了,2333

所以就这么A了,可能讲不大明白,看代码一定能弄明白。

下面是某弱逼的弱渣程序:

 1 #include<iostream>
 2 #include<cstdio>
 3 using namespace std;
 4 int n,m;
 5 int fa[2000500];
 6 int find(int x)
 7 {
 8     if(fa[x]==x)return x;
 9     else return fa[x]=find(fa[x]);
10 }
11 int main()
12 {
13     cin>>n>>m;
14     for(int i=1;i<=n;i++)
15     {
16         fa[i]=i+n;
17         fa[i+n]=i+n;
18     }
19     while(m--)
20     {
21         int x,y,p;
22         scanf("%d%d%d",&p,&x,&y);
23         if(p==1)
24         {
25             int f1=find(x);
26             int f2=find(y);
27             fa[f1]=f2;
28         }
29         else if(p==2)
30         {
31             fa[x]=find(y);
32         }
33         else
34         {
35             int f1=find(x),f2=find(y);
36             if(f1==f2)cout<<"Yes"<<endl;
37             else cout<<"No"<<endl;
38         }
39     }
40     return 0;
41 }

时间: 2024-11-06 20:26:14

并查集 专辑 之 虚空节点之谜的相关文章

LA 3027 Corporative Network(并查集,求某个节点到根节点的距离)

A very big corporation is developing its corporative network. In the beginning each of the N enterprisesof the corporation, numerated from 1 to N, organized its own computing and telecommunication center.Soon, for amelioration of the services, the co

并查集间单个节点的转移(UVa 11987 Almost Union-Find)

从来没有这么艰难地完成一道算法题过!经过8次失败之后总算提交成功了!所以决定写一篇博文,对并查集的相关内容做一些总结. 普通并查集的操作无非是两种,find_set(x)即找到节点x所在的集合的代表节点,或者是union_set(x,y),即将x和y所在的两个集合合并起来.如下图所示,有左右两个并集 通常,我们会选用并查集中父节点为自己的元素作为这个并查集的代表,例如图中的节点a和节点e.那么,我们如何通过集合中的一个节点找到该节点所在集合的代表节点呢?其实很简单,例如上图中的d节点,它首先通过

Travel(HDU 5441 2015长春区域赛 带权并查集)

Travel Time Limit: 1500/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 2404    Accepted Submission(s): 842 Problem Description Jack likes to travel around the world, but he doesn’t like to wait. Now, he is tr

POJ1962:Corporative Network(并查集)

Description A very big corporation is developing its corporative network. In the beginning each of the N enterprises of the corporation, numerated from 1 to N, organized its own computing and telecommunication center. Soon, for amelioration of the se

并查集&amp;MST

[HDU] 1198 Farm Irrigation 基础最小生成树★ 1598 find the most comfortable road 枚举+最小生成树★★ 1811 Rank of Tetris 并查集+拓扑排序★★ 3926 Hand in Hand 同构图★ 3938 Portal 离线+并查集★★ 2489     Minimal Ratio Tree dfs枚举组合情况+最小生成树★ 4081     Qin Shi Huang's National Road System 最

带权并查集

似乎好些天没写文章了,感慨万千啊. 一如既往,先介绍一下题目的需求吧,如下: 题目简述:某人想编写一个字典,该字典中存在正反两种关系,并且这种关系具有某种规则下的传递性质,如下: A 与 B 同义, B 与 C 同义,则 A 与 C同义 : A 与 B 同义, B 与 C 反义,则 A 与 C反义 : A 与 B 反义, B 与 C 同义,则 A 与 C反义 : A 与 B 反义, B 与 C 反义,则 A 与 C同义 . 此人最初定义部分字符串的正反关系,要求以此为基础将所有给定字符串之间的关

POJ Ubiquitous Religions (并查集)

Ubiquitous Religions Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 25255   Accepted: 12454 Description There are so many different religions in the world today that it is difficult to keep track of them all. You are interested in findi

2014 Super Training #8 A Gears --并查集

题意: 有N个齿轮,三种操作1.操作L x y:把齿轮x,y链接,若x,y已经属于某个齿轮组中,则这两组也会合并.2.操作Q x y:询问x,y旋转方向是否相同(等价于齿轮x,y的相对距离的奇偶性).3.操作D x :拆下齿轮x,并且x所在的齿轮组不会断开4.操作S x : 查询齿轮x所在的齿轮组有多少齿轮.并查集,维护父节点的同时,dis记录一下每个节点到根节点的距离,并且用num记录一下以x为根节点的集合有多少个元素. 由于涉及到删除操作,删除的是根节点的话会导致信息丢失,所以在删除的时候直

HDU ACM 1512 Monkey King-&gt;左偏树+并查集

题意:一开始有N只猴子,,每只都有一个力量值.,并且互不认识,后来 它们之间发生了M次斗争. 每次两次两只猴子a,b斗争是, a和 b都会从他们自己的朋友圈里拉出一个最强的朋友, 之后最强的这两只猴子打, 打完后两只猴子的力量值分别减半..并且 两只猴子的朋友圈的所有人都互相认识(也就是以后不会再打了).问题是对于每次斗争, 若a,b是朋友, 那么输出-1, 否则输出斗争后它们的朋友圈里最强猴子的力量值. 分析:要表示集合的合并查找操作就是并查集最好了:要维护每次的最大值,就可以使用大顶堆,但还