并查集

POJ 1611---The Suspects(并查集)

感情迁移 提交于 2019-11-26 19:09:43
题意:0疑似有传染病,和0在一起的都疑似被传染(这些人也会传染别人),求有多少个人可能有传染病; 直接代码+注释 (16ms) 1 #include<stdio.h> 2 #include<algorithm> 3 #include<string.h> 4 using namespace std; 5 6 const int maxn=20000000; 7 int par[maxn],m,n; 8 9 int find(int x) 10 { 11 if(x!=par[x]) 12 par[x]=find(par[x]); 13 return par[x]; 14 } 15 16 void unionn(int a,int b) 17 { 18 int fa=find(a); 19 int fb=find(b); 20 if(par[fb]!=fb) par[fa]=fb; //如果fb不是头 fa并入fb即头为fb 21 else par[fb]=fa; //如果fb是头 fb并入fa 22 } 23 24 int main() 25 { 26 while(scanf("%d%d",&n,&m)&&(m||n)){ 27 int p,a,b; 28 for(int i=0;i<=n;i++){ 29 par[i]=i; //每个人的头为自己 30 } 31 while(m--)

并查集

允我心安 提交于 2019-11-26 18:13:44
性质:   并查集是一种树型的数据结构。 注意这棵树的形态是不固定的,只要所有点的根节点都相同即可。 支持操作 合并两个集合(merge) 查询两个对象是否属于一个集合 (getfather) 支持撤销 (按秩合并) 基础实现: 1 int getfather(int x){ 2 if(fa[x]==x) return x; 3 return fa[x]=getfather(fa[x]); 4 } 5 void merge(int x,int y){ 6 x=getfather(x); 7 y=getfather(y); 8 //if(rank[x]<rank[y]) swap(x,y); 9 fa[y]=x; 10 //if(rank[x]==rank[y]) ++rank[x]; 11 } 复杂度:       路径压缩 O(nlogn) +按秩合并 树深<=O(logn) = O(n α(n)) 。 练习:   (一) [HAOI2006]旅行        题意 :有一个 n 个点,m 条边的图,求一条从 s 到 t 的路径,使得 最大值与最小值的比值最小。        范围 : n ≤ 500, m ≤ 5000 思路 :枚举最小边,然后加入比它大的边直到 s 和 t 连通为止。用并查集来支持加入一条边,查询 s,t 是否连通,时间复杂度 O(m2α(n))。 1

[并查集+逆向思维]Codeforces Round 722C Destroying Array

故事扮演 提交于 2019-11-26 17:37:43
Destroying Array time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output You are given an array consisting of n non-negative integers a 1 ,  a 2 , ...,  a n . You are going to destroy integers in the array one by one. Thus, you are given the permutation of integers from 1 to n defining the order elements of the array are destroyed. After each element is destroyed you have to find out the segment of the array, such that it contains no destroyed elements and the sum of its elements is maximum possible. The sum of elements in the empty segment

并查集与带权并查集---由浅入深

亡梦爱人 提交于 2019-11-26 17:33:22
并查集 基本概念 ​ 并查集,在一些有N个元素的 集合 应用问题中,我们通常是在开始时让每个元素构成一个单元素的集合,然后按一定顺序将属于同一组的元素所在的集合合并,其间要反复查找一个元素在哪个集合中。 ​ 并查集是一种树型的数据结构,用于处理一些不相交 集合 (Disjoint Sets)的合并及查询问题。常常在使用中以森林来表示。 实现原理 ​ 通过更新维护父亲节点使得,合并后的集合最终拥有同一个点根节点,拥有相同根节点即为同类。 Search 查找自己的根节点;(红圈标记为根节点)    Merge 合并两个节点在一个集合;(假设寻找合并节点5和2)    压缩路径;压缩路径可以使得在多次查询时,查询时间得到优化,具体过程是优化其结构,使得查询点的父亲节点为根节点。(上图压缩路径后得到)    代码实现 1 void init(){ // 初始化自己祖先就是自己 2 for(int i = 1 ; i<= n; i++){ 3 pre[i] = i; 4 } 5 } 6 7 int Search(int x){ // 递归寻找自己的祖先 8 return x == pre[x] ? x : pre[x] = Search(pre[x]); 9 } 10 11 void Merge(int x, int y){ // 合并两个节点 12 int fx = Search(x);

奇偶游戏(带权并查集)

久未见 提交于 2019-11-26 17:06:10
题目: 小A和小B在玩一个游戏。 首先,小A写了一个由0和1组成的序列S,长度为N。 然后,小B向小A提出了M个问题。 在每个问题中,小B指定两个数 l 和 r,小A回答 S[l~r] 中有奇数个1还是偶数个1。 机智的小B发现小A有可能在撒谎。 例如,小A曾经回答过 S[1~3] 中有奇数个1, S[4~6] 中有偶数个1,现在又回答 S[1~6] 中有偶数个1,显然这是自相矛盾的。 请你帮助小B检查这M个答案,并指出在至少多少个回答之后可以确定小A一定在撒谎。 即求出一个最小的k,使得01序列S满足第1~k个回答,但不满足第1~k+1个回答。 输入格式 第一行包含一个整数N,表示01序列长度。 第二行包含一个整数M,表示问题数量。 接下来M行,每行包含一组问答:两个整数l和r,以及回答“even”或“odd”,用以描述S[l~r] 中有奇数个1还是偶数个1。 输出格式 输出一个整数k,表示01序列满足第1~k个回答,但不满足第1~k+1个回答,如果01序列满足所有回答,则输出问题总数量。 数据范围 N ≤ 10 9 , M ≤ 10000 N≤109,M≤10000 输入样例: 10 5 1 2 even 3 4 odd 5 6 even 1 6 even 7 10 odd 输出样例: 3解题报告:咱们得到的是某段区间内的奇偶性,所以咱们可以转换一下思想,每个点x的存储就是从1

【PAT算法之路】 -- 并查集 1021 Deepest Root (25 分) C++解法

好久不见. 提交于 2019-11-26 16:13:16
【PAT算法之路】 – 专栏总揽 并查集在最近的PAT中也较常出现,并查集本身的代码非常优雅、简洁,如果第一次接触一定会惊叹它的简洁的。本身代码大概20行。在理解的基础上直接背下就行。我们选一个难一点的题来举例吧! 1021 Deepest Root (25 分) A graph which is connected and acyclic can be considered a tree. The height of the tree depends on the selected root. Now you are supposed to find the root that results in a highest tree. Such a root is called the deepest root. Input Specification: Each input file contains one test case. For each case, the first line contains a positive integer N (≤10 ​4 ​​ ) which is the number of nodes, and hence the nodes are numbered from 1 to N. Then N−1 lines follow, each

图论小专题B

谁都会走 提交于 2019-11-26 14:57:41
2 树 2.1 树的定义 一个只有 \(N-1\) 条边,且任意两个点连通的图叫做树。通过这样定义的树往往是一棵无根树,而我们通常会任意选定一个根节点使其变成有根树。有根树可以定义“父亲和儿子”的层次关系,这往往有利于构造最优子结构,进行DP和搜索等操作。 特别的,如果在树上任意加上一条边,那么整个树上就会多出一个环。我们称这样的树是“基环树”。基环树不是树,但是它只有一个环。将整个环作为一个“广义根”,然后将根和连在环上的子树分开处理,同样可以套用树的许多算法。 2.2 树上的DP算法 通常选定一个根,然后用DFS计算。至于递归接口应该放在转移之前还是之后呢?那就看方程怎么写了。在写程序的时候,只要满足“已知推未知”的原则就行。 如果给定一棵无根树,答案要求给出最优的根使得某个值最优化,这时可以采用“换根法”。先任意选定一个根计算出规划值 \(F_1\) ,然后从数学上推导出以任意点为根的规划值 \(F_2\) 。《进阶指南》上有相关的例题。 2.2.1 树的参量 子树大小size 最基础的量。转移方程简记为 \(F(x)=1+\sum F(\text{son}(x))\) 树的重心 和size一样。如果子树 \(x\) 的大小是 \(\text{size}(x)\) ,那么剩下树的大小就是 \(N-\text{size}(x)\) 。在求 \(\text{size}\)

#C++初学记录(奶酪#并查集)

て烟熏妆下的殇ゞ 提交于 2019-11-26 12:35:50
原题目: 牛客网 题目描述 : 现有一块大奶酪,它的高度为 h,它的长度和宽度我们可以认为是无限大的,奶酪中间有许多半径相同的球形空洞。我们可以在这块奶酪中建立空间坐标系, 在坐标系中,奶酪的下表面为 z = 0,奶酪的上表面为 z = h。 现在, 奶酪的下表面有一只小老鼠 Jerry, 它知道奶酪中所有空洞的球心所在的坐标。如果两个空洞相切或是相交,则 Jerry 可以从其中一个空洞跑到另一个空洞,特别地,如果一个空洞与下表面相切或是相交, Jerry 则可以从奶酪下表面跑进空洞; 如果一个空洞与上表面相切或是相交, Jerry 则可以从空洞跑到奶酪上表面。 位于奶酪下表面的 Jerry 想知道, 在不破坏奶酪的情况下,能否利用已有的空洞跑到奶酪的上表面去? 空间内两点 P1(x1,y1,z1) 、P2(x2,y2,z2) 的距离公式如下: dist(P_1,P_2)=\sqrt{(x_1-x_2)^2+(y_1-y_2)^2+(z_1-z_2)^2} dist(P 1 ,P 2 )= (x 1 −x 2 )2 +(y 1−y 2) 2 +(z 1−z 2) 2 输入描述: 每个输入文件包含多组数据。 输入文件的第一行,包含一个正整数 T,代表该输入文件中所含的数据组数。 接下来是 T 组数据,每组数据的格式如下: 第一行包含三个正整数 n, h 和 r,

种类并查集&amp;带权并查集

烈酒焚心 提交于 2019-11-26 01:42:11
P2024 (NOI2001)食物链 题目描述 动物王国中有三类动物 A,B,C,这三类动物的食物链构成了有趣的环形。A 吃 B,B 吃 C,C 吃 A。 现有 N 个动物,以 1 - N 编号。每个动物都是 A,B,C 中的一种,但是我们并不知道 它到底是哪一种。 有人用两种说法对这 N 个动物所构成的食物链关系进行描述: 第一种说法是“1 X Y”,表示 X 和 Y 是同类。 第二种说法是“2 X Y”,表示 X 吃 Y 。 此人对 N 个动物,用上述两种说法,一句接一句地说出 K 句话,这 K 句话有的是真 的,有的是假的。当一句话满足下列三条之一时,这句话就是假话,否则就是真话。 • 当前的话与前面的某些真的话冲突,就是假话 • 当前的话中 X 或 Y 比 N 大,就是假话 • 当前的话表示 X 吃 X,就是假话 你的任务是根据给定的 N 和 K 句话,输出假话的总数。 输入格式 从 eat.in 中输入数据 第一行两个整数,N,K,表示有 N 个动物,K 句话。 第二行开始每行一句话(按照题目要求,见样例) 输出格式 输出到 eat.out 中 一行,一个整数,表示假话的总数。 输入输出样例 输入 #1 复制 100 7 1 101 1 2 1 2 2 2 3 2 3 3 1 1 3 2 3 1 1 5 5 输出 #1 复制 3 说明/提示 1 ≤ N ≤ 5 ∗ 10