算法模板——并查集 2(支持快速即时查询本连通块内容,纯原创!)

实现功能:输入N,现在有N个数;接下来输入任意行,如果是"1 x y"则表示把x和y所在的块合并;如果是"2 x"则表示输出x所在的块的全部内容

原理:其实主要是自己创造了一个可并链line,he表示链头,ta表示链尾,然后对于不同块之间的合并就是直接把两条链对接,也就是一个的尾巴接到另一个的头上,构成新链(由于是链的直接叠加,所以可以做到严格的O(1),并且输出时输出多少复杂度就是多少,完全不存在额外复杂度)。然后同时用原本的普通数组并查集进行维护和追踪(理论值为O(logn)但实际上由于c[x]:=getfat(c[x])的优化导致实际测试结果远远小于这一复杂度)

复杂度:【合并操作O(1),查询O(块大小)(意味着复杂度几乎完全用来输出)】×N,相比于之前的算法对于即时处理的性能有所提高,但是只需要最终进行静态的全局处理时,两者差不太多,这个会略快些,传统程序代码略少些

(PS:值得注意的是,这种新的数据结构中千万要特判两个数字处于同一块的情况,必须避免同一条链首尾相接导致产生环!!!本程序41行continue那里有所体现。同时c[x]:=y之类的合并块语句以及merge(x,y)操作是有顺序之分的,两者顺序必须保持一致,不想原来的并查集顺序任意)

 1 type
 2     point=^node;
 3     node=record
 4                g:longint;
 5                next:point;
 6     end;
 7     line=record
 8                he,ta:point;
 9     end;
10 var
11    a:array[0..100000] of line;
12    c:array[0..100000] of longint;
13    i,j,k,l,m,n:longint;
14    p:point;
15 procedure merge(var p1,p2:line);inline;
16           begin
17                p1.ta^.next:=p2.he;
18                p1.ta:=p2.ta;
19                p2.he:=nil;p2.ta:=nil;
20           end;
21 function getfat(x:longint):longint;inline;
22          begin
23               if x<>c[x] then c[x]:=getfat(c[x]);
24               exit(c[x]);
25          end;
26 begin
27      readln(n);
28      for i:=1 to n do
29          begin
30               c[i]:=i;
31               new(p);p^.g:=i;p^.next:=nil;
32               a[i].he:=p;a[i].ta:=p;
33          end;
34      while true do
35            begin
36                 read(l);
37                 case l of
38                      1:begin
39                             readln(j,k);
40                             j:=getfat(j);k:=getfat(k);
41                             if j=k then continue;
42                             c[k]:=j;
43                             merge(a[j],a[k]);
44                      end;
45                      2:begin
46                             readln(j);
47                             j:=getfat(j);
48                             p:=a[j].he;
49                             while p<>nil do
50                                   begin
51                                        write(p^.g,‘ ‘);
52                                        p:=p^.next;
53                                   end;
54                             writeln;
55                      end;
56                 end;
57
58            end;
59 end.         
时间: 2025-01-01 05:46:42

算法模板——并查集 2(支持快速即时查询本连通块内容,纯原创!)的相关文章

并查集(判断一个图有几个连通块)

import java.util.Scanner; // 并查集 判断一个图中有几个联通块 public class UnionFind { private int[] father;// private int count;// 分量数量 public UnionFind(int N){ count=N; father=new int[N]; for(int i=0;i<N;i++){ father[i]=i; } } public int count() { return count; }

算法模板——并查集

实现功能——操作1:将两个数字合并到一个集合内:操作2:判断两个数字是否在一起 第6行是亮点,这个优化能快出不少,真的 1 var 2 i,j,k,l,m,n:longint; 3 c:array[0..100000] of longint; 4 function getfat(x:longint):longint;inline; 5 begin 6 if c[x]<>x then c[x]:=getfat(c[x]); //亮点在这里么么哒 7 exit(c[x]); 8 end; 9 be

普林斯顿公开课 算法1-10:并查集-优化的快速合并方法

应用 渗透问题 游戏中会用到. 动态连接 最近共同祖先 等价有限状态机 物理学Hoshen-Kopelman算法:就是对网格中的像素进行分块 Hinley-Milner多态类型推断 Kruskai最小生成树 Fortran等价语句编译 形态学开闭属性 Matlab中关于图像处理的bwlabel函数 渗透问题 一个N×N的矩阵,判断顶部和底部是否连通就是渗透问题. 下图中左侧的矩阵能渗透,右侧矩阵不能渗透. 渗透问题在电学.流体力学.社会交际中都有应用. 在游戏中可能需要生成一张地图,但是作为地图

算法:并查集

并查集是一种用途广泛的数据结构,能够快速地处理集合的合并和查询问题,并且实现起来非常方便,在很多场合中都有着非常巧妙的应用,.本文首先介绍并查集的定义.原理及具体实现,然后以其在最小生成树算法中的一个经典应用为例讲解其具体使用方法. 一 并查集原理及实现 并查集是一种树型的数据结构,用于处理一些不相交集合的合并及查询问题. 并查集在使用中通常以森林来表示,每个集合组织为一棵树,并且以树根节点为代表元素.实际中以一个数组father[x]即可实现,表示节点x的父亲节点.另外用一个变量n表示节点的个

HDU 2017 Code Lock (并查集的应用+快速幂)

链接:HDU 3461 题目大意: 题目的大意是一个密码锁上有编号为1到N的N个字母,每个字母可以取26个小写英文字母中的一个.再给你M个区间[L,M],表示该区间的字母可以一起同步"增加"(从'a'变为'b'为增1,'z'增1为'a').假如一组密码按照给定的区间进行有限次的"增加"操作后可以变成另一组密码,那么我们认为这两组密码是相同的.该题的目标就是在给定N.M和M个区间的前提下计算有多少种不同的密码. 根据题意,如果一个可调整的区间都没有的话,答案应该是26

HDU 3461 Code Lock(并查集的应用+快速幂)

* 65536kb,只能开到1.76*10^7大小的数组.而题目的N取到了10^7,我开始做的时候没注意,用了按秩合并,uset+rank达到了2*10^7所以MLE,所以貌似不能用按秩合并. 其实路径压缩也可以不用.............  题目的大意: 一个密码锁上有编号为1到N的N个字母,每个字母可以取26个小写英文字母中的一个.再给你M个区间[L,M],表示该区间的字母可以一起同步"增加"(从'a'变为'b'为增1,'z'增1为'a').假如一组密码按照给定的区间进行有限

分别利用并查集,DFS和BFS方法求联通块的数量

联通块是指给定n个点,输入a,b(1<=a,b<=n),然后将a,b连接,凡是连接在一起的所有数就是一个联通块: 题意:第一行输入n,m,分别表示有n个数,有输入m对连接点,以下将要输入m行(输入数据到文件截止): 输出:第一行要求输出联通块的个数,并在第二行分别输出每个联通块中点的数量,每个数之间以一个空格隔开. 样例 15 31 42 53 5输出:2 2 3样列2 9 81 22 33 43 74 54 67 87 9输出: 19 如果不明白的话可以画图试试,最多花半个小时,要是早这样不

模板 并查集

[模板]并查集 1 int find(int x) 2 { 3 int r = x; 4 while(father[r]!=r) 5 r = father[r]; 6 return r; 7 } 8 /* 9 int find(int x) 10 { 11 if(father[x] == x) 12 return x; 13 else 14 return father[x] =find(father[x]); 15 } 16 */ 17 18 void join(int x,int j) 19

HDU 1213 How Many Tables(模板——并查集)

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1213 Problem Description Today is Ignatius' birthday. He invites a lot of friends. Now it's dinner time. Ignatius wants to know how many tables he needs at least. You have to notice that not all the fri