热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

每日算法——并查集的应用

并查集是一种群众喜闻乐见的数据结构,其复杂度是数据结构中最奇葩的之一了,Tarjan证明其为阿克曼函数的反函数,在可以想象(不全面的解释啊)的范围内小于等于3。。。我们就把它当做O(1)吧。下面通

  并查集是一种群众喜闻乐见的数据结构,其复杂度是数据结构中最奇葩的之一了,Tarjan证明其为阿克曼函数的反函数,在可以想象(不全面的解释啊)的范围内小于等于3。。。我们就把它当做O(1)吧。下面通过几道基础的并查集来探查一下并查集的应用。递归调用并查集。

  最裸的并查集就只有表示一个集合的功能,支持动态的合并,查询两者是否属于一个集合,这部分内容太简单,请自行Baidu。

  在并查集上可以加入边权,成为加权并查集,一般来说这类题目形式比较单一,纯属个人娱乐吧。。

  加权并查集裸题——银河英雄传说

  这是一道最裸的加权并查集,对于每一个节点维护一个到最老最先的边权值和,再在祖先上维护一个Size,表示集合的大小。Wikioi上的题解有个水表说不能路径压缩。。。怎么可能嘛!!!我们仔细思考一下,每一个点在一个集合中只会被压缩一次,压缩之后就会被连接到祖先上,到祖先的权值和等于到原来的父亲的权值加上原来的父亲到祖先的权值和,只需要在压缩的时候更新一下就好了。合并的时候,把两个集合(不妨设A,B)合并在一起,假如把A并入B,则把A的祖先节点连在B的祖先上,边权设为B的Size。相当于把A集合直接接在B的后面,如此,这个问题就被很好的解决了。

  代码:

 1 #include 
2 #include
3 #include
4 #include
5
6 using namespace std;
7 struct spaceship
8 {
9 int father;
10 int len,maxlen;
11
12 spaceship(){len=0;maxlen=1;}
13 }sp[30010];
14
15 int get(int n)
16 {
17 if (sp[n].father==n) return n;
18 int m=get(sp[n].father);
19 sp[n].len+=sp[sp[n].father].len;
20 sp[n].father=m;
21 return sp[n].father;
22 }
23
24 void marry(int n,int m)
25 {
26 int nn=get(n);
27 int mm=get(m);
28 sp[nn].father=mm;
29 sp[nn].len+=sp[mm].maxlen;
30 sp[mm].maxlen+=sp[nn].maxlen;
31 }
32
33 int main()
34 {
35 int n;
36 scanf("%d",&n);
37 for (int i=1;i<=30000;i++) sp[i].father=i;
38 for (int i=1;i<=n;i++)
39 {
40 char ch;
41 int j,k;
42 char s[5];
43 scanf("%s",s);
44 if (s[0]=='M')
45 {
46 scanf("%d%d",&j,&k);
47 marry(j,k);
48 }
49 else
50 {
51 scanf("%d%d",&j,&k);
52 if (get(j)==get(k))
53 {
54 printf("%d\n",abs(sp[j].len-sp[k].len)-1);
55 }
56 else
57 printf("-1\n");
58 }
59 }
60 return 0;
61 }
View Code

  上面这道是裸题,下面有一个看起来不裸的的水题:

  加权并查集弱题——食物链

  初一看这道题似乎和并查集关系不大,但是仔细观察可以发现,不同的个体存在一些关系。我们将物种设为0,1,2三种,则给出的条件分为两种——1.两个个体数字(物种)相同。2,个体A数字=(个体B数字+1)%3 。是否有了一点发现呢,如果是相同的数字,并且不属于同一个集合,就想合并办法让他们之间的权值变为0(mod 3),同理,可以让其数字变为1或2(mod 3),只需要在路径压缩的时候取模就行了。水题解决,代码用下一道的吧。。。

  原创题——魏总数星星

  

魏总数星星

star.cpp/c/pas

【描述】

魏总,也就是DP魏,非常喜欢星星,有一天他躺在草坪上数星星。天上共有i颗星星,魏总把天空分成了K个扇形,绕着天空的中心——月亮排布。月亮看见魏总喜欢星星,非常不爽,她就想考一下魏总。月亮给出n队星星的相互关系,形如a b p表示b星星在a星星所在扇形区域的顺时针方向第p个扇形内(0<=p<=k)(p==0时表示在同一个扇形内)。最后月亮要询问m次,形如a b表示询问a b两星是否在一个扇形内,是则输出“Yes”,不是则输出“No”,不知道则输出“Unknown”。由于月亮看魏总喜欢星星变得心情急躁,可能有一些关系与前面的关系矛盾,则这些关系无效。月亮说如果不能把她的所有询问答对就要发出强光,让魏总看不到星星,而本来是大神的魏总因为想见到星星不能编程,只有把这个艰巨的任务交给你了。

【输入】

第一行四个整数iknm表示i个星星,k个扇形,n个关系,m个询问。

接下来n行,每行三个整数a b p 表示表示b星星在a星星所在扇形区域的顺时针方向第p个扇形内。

接下来m行,每行两个整数a b表示询问ab是否在同一个扇形内。

【输出】

m行,每行为“Yes”或“No”或“Unknown”对应每一个询问

【样例输入】

5 5 3 3

1 2 1

2 4 2

4 5 2

1 2

3 4

1 5

【样例输出】

No

Unknown

Yes

【数据范围】

20%,魏总数不超过100个星星,月亮询问不超过100次,天空被分成不超过10个区域。

50%,魏总数不超过4000个星星,月亮询问不超过4000次,天空被分成不超过1000个区域。

100%,魏总数不超过100000个星星,月亮询问不超过100000次,天空被分成不超过10000个区域,关系数少于200000

 

其实很容易发现这道题和食物链是一模一样的,只不过把边权值改为了比较大的数,只需稍微改一下代码即可,代码如下:

 

 1 #include 
2 #include
3 #include
4 #include
5
6 using namespace std;
7 struct star
8 {
9 int father;
10 int len;
11
12 star()
13 {
14 father=0;
15 len=0;
16 };
17 }st[100010];
18 int mod;
19 int get(int now)
20 {
21 if (st[now].father==now)
22 {
23 return now;
24 }
25 int f=get(st[now].father);
26 st[now].len=(st[now].len+st[st[now].father].len)%mod;
27 if (st[now].len==0) st[now].len=mod;
28 st[now].father=f;
29 return f;
30 }
31 void marry(int a,int b,int l)
32 {
33 int bf=get(b);
34 int af=get(a);
35 int len=st[a].len+l;
36 len=len % mod;
37 if (l>=st[b].len)
38 {
39 st[bf].father=a;
40 st[bf].len=l-st[b].len;
41 }
42 else
43 {
44 st[bf].father=a;
45 st[bf].len=mod+l-st[b].len;
46 }
47 }
48
49 int main()
50 {
51 freopen ("star.in","r",stdin);
52 freopen ("star.out","w",stdout);
53 int n,m,k;
54 scanf("%d%d%d%d",&n,&mod,&m,&k);
55 for (int i=1;i<=n;i++)
56 {
57 st[i].father=i;
58 }
59 int a,b,p;
60 for (int i=1;i<=m;i++)
61 {
62 scanf("%d%d%d",&a,&b,&p);
63 if (get(a)!=get(b))
64 {
65 marry(a,b,p);
66 }
67 }
68 for (int i=1;i<=k;i++)
69 {
70 scanf("%d%d",&a,&b);
71 if (get(a)!=get(b))
72 {
73 printf("Unknown\n");
74 }
75 else
76 {
77 if (st[a].len%mod==st[b].len%mod) printf("Yes\n");
78 else printf("No\n");
79 }
80 }
81 return 0;
82 }
View Code

 

总结:并查集可以处理没有分离操作的一类问题,可以在极快的时间内处理元素间相互关系的问题,好写好用,就是没什么地方用。。。

 


推荐阅读
  • JSOI2010 蔬菜庆典:树结构中的无限大权值问题
    本文探讨了 JSOI2010 的蔬菜庆典问题,主要关注如何处理非根非叶子节点的无限大权值情况。通过分析根节点及其子树的特性,提出了有效的解决方案,并详细解释了算法的实现过程。 ... [详细]
  • 本题来自WC2014,题目编号为BZOJ3435、洛谷P3920和UOJ55。该问题描述了一棵不断生长的带权树及其节点上小精灵之间的友谊关系,要求实时计算每次新增节点后树上所有可能的朋友对数。 ... [详细]
  • 本题探讨了在大数据结构背景下,如何通过整体二分和CDQ分治等高级算法优化处理复杂的时间序列问题。题目设定包括节点数量、查询次数和权重限制,并详细分析了解决方案中的关键步骤。 ... [详细]
  • Coursera ML 机器学习
    2019独角兽企业重金招聘Python工程师标准线性回归算法计算过程CostFunction梯度下降算法多变量回归![选择特征](https:static.oschina.n ... [详细]
  • 利用Selenium与ChromeDriver实现豆瓣网页全屏截图
    本文介绍了一种使用Selenium和ChromeDriver结合Python代码,轻松实现对豆瓣网站进行完整页面截图的方法。该方法不仅简单易行,而且解决了新版Selenium不再支持PhantomJS的问题。 ... [详细]
  • 本文介绍了如何使用JavaScript的Fetch API与Express服务器进行交互,涵盖了GET、POST、PUT和DELETE请求的实现,并展示了如何处理JSON响应。 ... [详细]
  • 本文探讨了如何通过预处理器开关选择不同的类实现,并解决在特定情况下遇到的链接器错误。 ... [详细]
  • 本文介绍如何利用栈数据结构在C++中判断字符串中的括号是否匹配。通过顺序栈和链栈两种方式实现,并详细解释了算法的核心思想和具体实现步骤。 ... [详细]
  • Redux入门指南
    本文介绍Redux的基本概念和工作原理,帮助初学者理解如何使用Redux管理应用程序的状态。Redux是一个用于JavaScript应用的状态管理库,特别适用于React项目。 ... [详细]
  • 本文介绍了如何在多线程环境中实现异步任务的事务控制,确保任务执行的一致性和可靠性。通过使用计数器和异常标记字段,系统能够准确判断所有异步线程的执行结果,并根据结果决定是否回滚或提交事务。 ... [详细]
  • 本文详细探讨了 org.apache.hadoop.ha.HAServiceTarget 类中的 checkFencingConfigured 方法,包括其功能、应用场景及代码示例。通过实际代码片段,帮助开发者更好地理解和使用该方法。 ... [详细]
  • 二维几何变换矩阵解析
    本文详细介绍了二维平面上的三种常见几何变换:平移、缩放和旋转。通过引入齐次坐标系,使得这些变换可以通过统一的矩阵乘法实现,从而简化了计算过程。文中不仅提供了理论推导,还附有Python代码示例,帮助读者更好地理解这些概念。 ... [详细]
  • 本文详细介绍了优化DB2数据库性能的多种方法,涵盖统计信息更新、缓冲池调整、日志缓冲区配置、应用程序堆大小设置、排序堆参数调整、代理程序管理、锁机制优化、活动应用程序限制、页清除程序配置、I/O服务器数量设定以及编入组提交数调整等方面。通过这些技术手段,可以显著提升数据库的运行效率和响应速度。 ... [详细]
  • 基于Node.js、Express、MongoDB和Socket.io的实时聊天应用开发
    本文详细介绍了使用Node.js、Express、MongoDB和Socket.io构建的实时聊天应用程序。涵盖项目结构、技术栈选择及关键依赖项的配置。 ... [详细]
  • 在 Android 开发中,通过 Intent 启动 Activity 或 Service 时,可以使用 putExtra 方法传递数据。接收方可以通过 getIntent().getExtras() 获取这些数据。本文将介绍如何使用 RoboGuice 框架简化这一过程,特别是 @InjectExtra 注解的使用。 ... [详细]
author-avatar
心语忆录_288
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有