并查集

POJ1611 The Suspects (并查集)

坚强是说给别人听的谎言 提交于 2020-10-29 18:50:07
本文出自: http://blog.csdn.net/svitter 题意:0号学生染病,有n个学生,m个小组。和0号学生同组的学生染病,病可以传染。 输入格式:n,m 数量 学生编号1,2,3,4 //m个分组 题解:最为典型的并查集。 解法一:求出所有的集合,然后求出0的parent,把parent为0的parent所有学生求出。 解法二:在计算的过程中统计total; 解法一:(一开始用的Vim写的在POJ上交出现 访问禁止错误- - 不知道又神奇的碰上了什么BUG,删了main函数中几个换行符就好了) #include <iostream> #include <stdio.h> using namespace std; int stu[30001]; //the num of stu, group int n, m; void init() { for(int i = 0; i < n; i++) stu[i] = i; } int getParent(int a) { if(a == stu[a]) return a; else return stu[a] = getParent(stu[a]); } void Merge(int a, int b) { if(getParent(a) == getParent(b)) return; else stu[getParent

并查集判树 poj 1308

六月ゝ 毕业季﹏ 提交于 2020-04-08 10:59:17
例题: poj 1308 题目大意比较简单,对任意两个点,有且仅有一条道路,也就是一棵树。 题解:一棵树中,肯定是不能有环的,而且只能由一个根节点。(没认真读题,只知道在那里判环。。。。),所以这个题先判环然后就是判根节点的唯一性。 //#include<bits/stdc++.h> #include<cstdio> #include<iostream> #include<algorithm> using namespace std; const int N=1e5+7; int fa[N]; bool mark[N]; int find(int x){ return fa[x]==x? x:fa[x]=find(fa[x]); } bool unite(int x,int y){ x=find(x);y=find(y); if(x==y) return 1; else { fa[x]=y; return 0; } } int main(){ int n,m,time=0; while(cin>>n>>m){ if(n==-1&&m==-1) break; for(int i=0;i<=100000;i++) { fa[i]=i;mark[i]=0; } if(n==0&&m==0) { printf("Case %d ",++time); cout<<"is a tree."<

JZOJ5373【NOIP2017提高A组模拟9.17】信仰是为了虚无之人

你。 提交于 2020-04-05 20:52:09
题目 分析 我们发现,如果[l,r]的异或和为k是真要求,有且仅当不存在[l,i]和[i,r]两个区间的异或和不为k。 我们用带权并查集了维护这些,但是,由于区间不连续,我们将点权移到边上,对于区间[l,r]的点权异或和,变成[l,r+1]边权异或和。并查集合并时将大点连向小点, 最后通过并查集求异或点缀和,如果某个点没有限制,值为零。 #include <cmath> #include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <algorithm> #include <queue> #include <map> const int maxlongint=2147483647; const int mo=1e9+7; const int N=200005; using namespace std; int b[N*2][3],fa[N],v[N],n,m,czy,ans,tot,sum[N],la[N*2],ne[N*2],vv[N*2],to[N*2]; int get(int x) { if(x==fa[x]) return x; int y=get(fa[x]); v[x]^=v[fa[x]]; return fa[x]=y; } int main() {

并查集题目整理

若如初见. 提交于 2020-04-04 09:15:02
并查集 之前写最小生成树的时候对这一部分的知识也并没有十分详细的整理 近天做了一些用到并查集的题目,来整理一下 知识回顾 首先,先来回顾一下有关并查集的内容 <1> 定义 并查集是一种树型的数据结构,用于处理一些不相交集合(Disjoint Sets)的合并及查询问题。常常在使用中以森林来表示。 集就是让每个元素构成一个单元素的集合,也就是按一定顺序将属于同一组的元素所在的集合合并。 <2>初始化 把每个点所在集合初始化为其自身。 通常来说,这个步骤在每次使用该数据结构时只需要执行一次,无论何种实现方式,时间复杂度均为O(N)。 <3>查找 查找元素所在的集合,即根节点。 <4>合并 将两个元素所在的集合合并为一个集合。 通常来说,合并之前,应先判断两个元素是否属于同一集合,这可用上面的"查找"操作实现。 主要处理的是有关这一部分的两个例题 Luogu P1550 [USACO08OCT]Watering Hole G 解题思路: 这个题给我的第一印象是最小生成树的Kruscal 但是仔细一读题发现其实有许多小的细节与最精简的Kruscal是有差别的 例如题目中有一个挖井的操作 那就讲问题拆开来看 part1:如何解决连牧场的操作 这里不难想到去直接最小生成树维护 很显然牧场之间的连线满足生成树的性质 part2:如何解决挖井的问题 考虑在不影响part1的前提下实现

并查集01--[Quick Find&&Quick Union]

荒凉一梦 提交于 2020-03-28 11:29:12
1.并查集 1.1需求分析 1.2并查集(Union Find) 1.3如何存储数据 1.4接口定义 1.5初始化 2.实现方式 2.1Quick Find--Union 2.2Quick Find--Find 2.3Quick Union --Union 2.4quick union--Find 2.5Quick union 优化 2.6quick union--基于size优化 2.7quick union 基于rank优化 2.8 路径压缩(Path Compression) 2.9路径分裂(Path Spliting) 2.10路径减半(Path Halving) 3.总结 4.自定义类型 来源: https://www.cnblogs.com/ggnbnb/p/12586205.html

3.26 CodeForces练习

纵饮孤独 提交于 2020-03-26 23:43:35
C. News Distribution (1400)(并查集求连通块点的个数) 分析:给定n,m,n表示n个用户,m表示组数,每组有很多人。我们可以通过并查集求连通块内的点的个数。 #include <iostream> #include <cstdio> #include <cstring> #include <vector> #include <algorithm> using namespace std; const int N = 500005; int p[N]; int sz[N]; int find(int x) { if (p[x] != x) p[x] = find(p[x]); return p[x]; } int main() { int n, m; scanf("%d%d", &n, &m); for (int i = 1; i <= n; ++i) p[i] = i, sz[i] = 1; for (int i = 1; i <= m; ++i) { int k; scanf("%d", &k); if (k == 0) continue; else { int last; scanf("%d", &last); if (k >= 2) { int d; for (int j = 2; j <= k; ++j) { scanf("%d", &d);

[转] [博客园] 迷宫生成算法x4

余生长醉 提交于 2020-03-25 22:44:20
简介 所谓迷宫生成算法,就是用以生成随机的迷宫的算法 迷宫生成算法是处于这样一个场景: 一个row行,col列的网格地图,一开始默认所有网格四周的墙是封闭的 要求在网格地图边缘,也就是网格的边上打通2面墙 所有网格都至少保证网格周围至少有一堵墙打通 所有网格都能通过打通的墙能形成一条通路 博主已实现RecursiveBacktracking(递归回溯),RecursiveSegmentation(递归分割),随机Prim算法,Kruskal+并查集四种迷宫生成算法,这篇文章主要对这四种算法进行简要的介绍 基于Unity的迷宫生成算法代码实现 Github链接 递归回溯算法 复杂度 空间:O(n),时间:O(n),n为迷宫节点数row*col 原理 以一个栈作为辅助的数据结构,用以记录打通区域的顺序,用以回溯 一开始随机在地图中选择一个区域,加入栈。 之后在之前选择的区域周围随机选择一个未打通的区域,将新选择的区域和之前选择区域的墙打通,并把新的区域的加入栈 如果四周的区域都打通,就让栈出栈,将当期所选择的区域设置栈新的栈顶,表示回退到上一个区域 之后递归的按之前的步骤选择下一个区域直到所有区域都被打通 缺点 这种算法实现思路极为简单,但通路过于明显,甚至有可能会出现上图中的迷宫,很尴!!! 递归分割算法 复杂度 递归空间复杂度:O(row * col),最好时间复杂度:O

Java 编写 并查集 算法—— [针对自己最新确认的代码编写规范的]

纵然是瞬间 提交于 2020-03-24 21:44:29
日期: 2020.03.24 博客期: 168 星期二    【博客前言】     众所周不知啊,我在上大一的时候,进入了我们学校的 ACM-算法竞赛协会,当时学习的成员还不多,但是学习氛围很好,我上的第一堂课就是关于并查集的使用,我就用当时才学完的 C语言实现了。我对于这个算法可以说是记忆犹新吧!这个例子我学了 C++以后也实现过,那么今天就轮到我使用 Java 在设计模式和最近新确定好的 Java代码规范的基础下再来实现这个“并查集”算法!    【代码功能】     并查集的适用场景:在分散的许多结点中,人为的添加一些点到点的线,使其构成多条树(每条树对应一个分组),可以判定两个结点是否有线路可以流通、可以人为地将两个分组连接起来。 【实装代码】     com.bcj 包:       数字并查集类: 1 package com.bcj; 2 3 import java.util.ArrayList; 4 import java.util.List; 5 6 // Readme: 7 // 8 // English Name: UnionCheckingSet Class 9 // Chinese Name: 数字并查集类 10 // 11 // Writen by NS-Studio in 2020-03-24 17:41 12 // 13 public class

hdu 2120(并查集判环)

亡梦爱人 提交于 2020-03-22 07:46:54
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=2120 思路:简单的并查集判环应用,即如果当前的两个节点在同一个集合中,那么说明存在环了,ans++。 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 #define MAXN 1000+10 7 int parent[MAXN]; 8 int n,m; 9 10 int Find(int x) 11 { 12 int s; 13 for(s=x;parent[s]>=0;s=parent[s]) 14 ; 15 while(x!=s){ 16 int tmp=parent[x]; 17 parent[x]=s; 18 x=tmp; 19 } 20 return s; 21 } 22 23 void Union(int u,int v) 24 { 25 int r1=Find(u),r2=Find(v); 26 if(r1==r2)return ; 27 if(parent[r1]<parent[r2]){ 28 parent[r1]+=parent[r2]; 29 parent[r2]=r1; 30 }else { 31

天神下凡

断了今生、忘了曾经 提交于 2020-03-17 06:16:15
https://zybuluo.com/ysner/note/1176892 题面 给出 \(n\) 个圆心同在 \(x\) 轴上的圆,问圆的轮廓将平面分为几块?( 保证圆互不相交 ) \(n\leq3*10^5\) \(r\leq10^9,x\leq10^9\) 解析 经过观察,可以发现,如果一个圆的直径被其它小圆的直径完全覆盖,就会产生额外一贡献。 因为圆在一条直线上,我们只用关心其在直线上的一部分,即可以 用直径代替一个圆 。 一条直线再次被覆盖?能想到什么? 线段树?栈? \(method\ 1\) 并查集 据说这是我的原创方法? 在手玩样例时,我发现, 每次产生贡献的前一步都是把已联通(通过圆相切的方式)的两个点作为一个圆直径的两端点 。 如何判断两点是否联通? 每覆盖一条直线,两端点就连通了,此时两端点中间的点就没用了,直接把两端点纳入同一并查集即可。 当然,两端点联通有一种方式叫 在同一圆直径的两端 ,即存在同圆,这会影响答案,要排序除掉。 由于半径范围(即直径两端点范围)过大,要用 \(map\) 。 于是复杂度达到了 \(O(nlog^2n)\) ,但时间比为 \(1.16s/3s\) ,不虚。(并查集+ \(map\) ) 可以通过离散化达到 \(O(nlogn)\) #include<iostream> #include<cmath> #include