抱歉这么久才写出一篇文章,最近进度有点慢。这么慢是有原因的,我在想如何改进能让大家看系列文章的时候更方便一些,现在这个问题有了答案,在以后的推送中,我将尽量把例题和相关知识点在同一天推出,其次在代码分享方面,我也做了改进,对应当加入注释的地方略微加了注释。


先介绍一下今天分享的题目

题目简述:有 n 个人,其中存在很多对朋友关系(不排除有的人没有朋友),这种朋友关系满足对称、传递性质(是否是自反关系对这道题没有影响),即 如果A 和 B 是朋友,就有 B 和 A 是朋友; 如果 A 和 B 是朋友且 B 和 C 是朋友,就有 A 和 C 也是朋友关系。简言之:满足朋友关系的人要么有直接的朋友关系,要么两人有共同的朋友。

由上述特性可以在一个群体间建立起很多个关系网络。

分析一下建立的朋友关系网络具备的特征。对称性说明该关系是无向关系,此外该网络还满足传递性,举个例子:如果其中一个关系网络中有 1 、2、 3、 4  这四个人,

已知

1  < - > 2

2  < - > 3

1  < - > 4

由  1  < - > 2 与 2  < - > 3  可以得出 1 < - > 3

由  1  < - > 2 与 1  < - > 4  可以得出 2 < - > 4

由  2  < - > 3 与 2  < - > 4  可以得出 3 < - > 4

总结:

编号 1 的朋友为:2 、3 、4

编号 2 的朋友为:1 、3 、4

编号 3 的朋友为:1 、2 、4

编号 4 的朋友为:1 、2 、3

由此可以得出结论,这个网络中任意两个人都必须满足朋友关系,且一个人一旦能与该网络某一个人发生关系,此人同样与其他所有人都有关系。如果一个人有朋友,那么这些互为朋友的人必然能够形成一个封闭的关系网络,这就形成了两个极端:要么孤身一人没有朋友,要么就必须和所在关系网络中所有人成为朋友。用图论的知识解释:根据朋友关系的对称性可以得出这个题目中形成的图是无向图,形成的关系网络要么是平凡图(只有一个孤立点),要么是完全图(任意两点之间均连通)。


题目要求:第一行给出总人数 n 和 总关系对数 m,将 n 个人从 1 到 n 进行编号,并给出满足朋友关系的 m 对编号,试判断给出的 m 对关系是否构成了满足题目所述朋友关系的网络体系。是输出 YES ,否则输出 NO 。

输入输出数据要求如下:

m 和 n 均不超过 150 000 。

测试样例如下:


在对题目梗概了解之后,不妨先来观察一下测试样例。

以第一组测试样例为例进行分析:

n = 4 ,m = 3 ,由 3 对朋友关系可以建成如下关系网络体系:

由上图可以看出 左半部分满足完全图,右半部分满足平凡图,该体系满足题目所要求的朋友关系,因此输出答案 YES 。

再来看第二组测试数据:

n = 4 ,m = 4 ,由所给四对关系可以建成如下关系网络体系:

由上图可以看出,4 与 2 、1均未直接连接,因此不满足完全图条件,答案为 NO 。


在对上面两个样例进行分析后发现,判断一个关系网络体系是否满足条件,只需要对每一个连通分量进行判断,如果其中存在一个既不是完全图也不是平凡图的分量,那么这个体系就不满足条件。

人眼去观察的时候,可能一眼就能看出一个连通分量甚至一个关系网络体系是不是满足条件,但是计算机怎么判断呢?计算机判断的时候,必须有一个固定模式形成的标准,用这个标准和形成的实例进行对比,完全匹配的是正确的,不完全匹配则是错误的。这个过程分为以下两步:

第一步:应该建立起输入信息所给的关系网络体系,并将其储存。建立关系网络体系分为两个方面,第一个方面,由于题目要求判断给定的关系是否满足条件,因此要将原来给定的 m 对关系存储,第二个方面,由于朋友关系本身具备的特征,要将对称性和传递性的关系体现出来,也就意味着,在输入的过程中,需要对图进行完善,将对称性和传递性所产生的关系填充。因此,该题目必须建立两个独立的结构,一个单纯存储题目给定的关系,另一个则用来存储经过修正的关系网络体系。

第二步:将原关系和修正关系进行对比。


理论知识介绍完毕,下面是具体的实现方案:

和以往一样,介绍普通思路和修改思路两种方案

方案一

  1. 原关系的存储

    原来的关系给的是 m 对朋友的编号(不重复),由于要满足对称性关系,因此应该存储双向关系,回忆一下,最直观的存储图的结构是--邻接矩阵,说得直白一点就是二维数组,这种结构存储图的好处是,查找任意两个元素之间的关系,时间复杂度是 o(1),但这种结构缺点比较致命,空间利用率不高且对整个图进行遍历时,时间消耗太多。本题m、 n 的范围给的是150 000,开二维数组来实现肯定不现实(我不会告诉你我尝试的时候程序崩溃到连数字都无法读入);另外还有一种方法用来存储图结构--邻接表,这种结构空间利用率是比较高的,但是,链表的实现编写起来比较麻烦,稍有不慎,就会有指针越界的错误出现。不过在对链表操作熟悉的前提下,也不失为一种可行方案。

  2. 修正关系的存储

    修正关系要满足对称性和传递性,根据题目所给的要求,相互之间存在朋友关系的人,放在同一个集合中即可。为什么仅仅存入同一个集合就可以呢?因为本题中任一关系网络均为无向完全图,也就是每个关系网络中的任何一个个体都与同一关系网络内其余所有个体相联系,所有成员不存在特殊需要标记的特性。如果仅仅需要将所有成员分成若干个集合,那么用并查集来实现这一步骤是再合适不过了。

    并查集实现的功能:按照某种特定的关系,将所有元素划分为若干集合,并在每个集合中选出一个代表元素(俗称father)来代表该集合,这种行为类似于在学校这样的大环境中分了若干个班级,每个班级选出一个班长,由班长作为班级的代表和外界进行沟通交流。

  3. 原关系和修正关系的对比

由于修正关系是按照正确的关系建立的关系网络,因此需要判断的是原关系是否有不同于修正关系的地方,即对于修正关系中出现的每一对关系,原关系图中是否存储了该关系。按照这种思路每在修正关系网络中找到一对关系,就需要在存储原关系的邻接矩阵(或邻接表)中查找该关系是否存在。这种思路的时间复杂度远远超过 o(n*n),在150 000 这样规模的数据上是不可取的。

原关系和修正关系的存储结构比较好改进,但是关系对比这个方向怎么改进?既然遍历会超时,能不能换个思路进行改进呢?现在重新捋一下思路,完全图有很多性质,我们能不能利用它的某些性质避开对整个图的遍历呢?对于一个 n 个节点的完全图,其中的每一个节点必然与其余节点相连接,也就意味着与之相关联的关系个数为 n-1,那么只需要确定每个关系网络中所含的节点的个数 n ,再对原图进行遍历,判断每个节点是否与所在关系网络满足上述关系即可。

现在问题转化成了两个简单的问题:

一、求修正关系网络体系中连通分支的个数以及对应的节点数。

二、求解原关系网络体系中与每个节点相关的关系个数并与修正关系中对应的个数进行对比。

准备好所有需要用的数据,只需要一次遍历,时间复杂度为 o(n)就可完成。这就产生了如下方案。

方案二

  1. 原关系的存储

    利用 STL 中的 vector 容器,实现对原关系网络体系的动态存储,开 1e6 的 vector 数组 g[1e6],将与编号 i 相关的所有个体存入 g[i]分量中。这个时候,直接调用 g [i]. size()函数,就可求出与 i 有关的关系个数。(需要注意的一点就是,在此建立的关系是双向的)

  2. 修正关系的存储

    对于修正关系网络体系,可以使用并查集思想对 father 数组进行修正,由于在原关系和修正关系的对比过程中,用到的只有连通分支的代表和节点总数的对应关系,因此,可以利用STL 中的 map 容器,将两者的映射关系存入即可。

  3. 原图和修正图的对比

    逐个比较编号 i 的 分量的关系数 g [i]. size()和 map 中 存储的 i 所在关系网络    的节点数 map[ find( i )]是否满足

    map[ find( i )]-1 = g[i] . size()

这就实现了 建图而避开对图遍历 的目的。


以上是理论介绍,有需要查看代码的朋友打开网页http://paste.ubuntu.com/24324517/。

stl 和并查集应用的更多相关文章

  1. Codeforces 1131 F. Asya And Kittens-双向链表(模拟或者STL list)+并查集(或者STL list的splice()函数)-对不起,我太菜了。。。 (Codeforces Round #541 (Div. 2))

    F. Asya And Kittens time limit per test 2 seconds memory limit per test 256 megabytes input standard ...

  2. HDU 3926 并查集 图同构简单判断 STL

    给出两个图,问你是不是同构的... 直接通过并查集建图,暴力用SET判断下子节点个数就行了. /** @Date : 2017-09-22 16:13:42 * @FileName: HDU 3926 ...

  3. c++并查集配合STL MAP的实现(洛谷P2814题解)

    不会并查集的话请将此文与我以前写的并查集一同食用. 原题来自洛谷 原题 文字稿在此: 题目背景 现代的人对于本家族血统越来越感兴趣. 题目描述 给出充足的父子关系,请你编写程序找到某个人的最早的祖先. ...

  4. HZNU-ACM寒假集训Day1小结 STL 并查集

    常用STL 1.优先队列 priority_queue 内部是用堆(heap)实现的 priority_queue<int> pq; 默认为一个“越小的整数优先级越低的优先队列” 对于一些 ...

  5. ZOJ2334 Monkey King 并查集 STL

    题意:两家原始人(猴)打交道后成为一家猴,打交道时两家分别派出最帅的两位猴子,颜值各自减半,问每次打交道后新家族最帅的猴子的颜值.当然,已经是一家子就没有必要打交道了,因为没有猴希望颜值降低,毕竟还得 ...

  6. Codeforces 731 C.Socks-并查集+STL(vector+map)

      C. Socks   time limit per test 2 seconds memory limit per test 256 megabytes input standard input ...

  7. codeforces 766 D. Mahmoud and a Dictionary(种类并查集+stl)

    题目链接:http://codeforces.com/contest/766/problem/D 题意:给你n个单词,m个关系(两个单词是反义词还是同义词),然后问你所给的关系里面有没有错的,最后再给 ...

  8. [NOI2015] 品酒大会 - 后缀数组,并查集,STL,启发式合并

    [NOI2015] 品酒大会 Description 对于每一个 \(i \in [0,n)\) 求有多少对后缀满足 LCP 长度 \(\le i\) ,并求满足条件的两个后缀权值乘积的最大值. So ...

  9. CF722C. Destroying Array[并查集 离线]

    链接:Destroying Array C. Destroying Array time limit per test 1 second memory limit per test 256 megab ...

随机推荐

  1. MyEclipse2014安装图解

    MyEclipse2014安装图解.. ------------------ ------------------ ------------------ ------------------ ---- ...

  2. <当幸福来敲门>之一些很喜欢的台词收藏

    <当幸福来敲门> ================ ================

  3. 一起来学linux:目录与路径

    p { margin-bottom: 0.25cm; line-height: 120% } 首先介绍目录相关的路径的表示法: 1 . 代表此目录 2 .. 代表上一层目录 3 – 代表前一个工作目录 ...

  4. WeQuant交易策略—Dual Thrust

    Dual Thrust策略 策略介绍 Dual Thrust是一个趋势跟踪系统,由Michael Chalek在20世纪80年代开发,曾被Future Thruth杂志评为最赚钱的策略之一. Dual ...

  5. tensorflow笔记(五)之MNIST手写识别系列二

    tensorflow笔记(五)之MNIST手写识别系列二 版权声明:本文为博主原创文章,转载请指明转载地址 http://www.cnblogs.com/fydeblog/p/7455233.html ...

  6. Java开发相关命名规范

    JAVA文件命名规范 1.类命名 抽象类以 Abstract 或者 Base 开头.异常类以 Exception 作为后缀.枚举类以 Enum 作为后缀.工具类以 Utils 作为后缀(相应的包名最后 ...

  7. 基于linux vim环境python代码自动补全

    (一)简述 在使用vim编写python文件的过程中,默认的vim不会实现代码补全功能,在写程序或者是改程序的时候不是很方面,很容易出错,但是vim提供了各种插件,其中包括这个python文件的自动补 ...

  8. ssm整合说明与模板-Spring Spring MVC Mybatis整合开发

    ssm整合说明 spring+spring mvc+mybatis 说明 源码下载 由于之前存在ssh框架,spring+struts+hibernate,其中spring负责aop与ioc,所以一般 ...

  9. [C#] 如何截取完整的网页图片

    前言 有时候浏览到非常有用的网页时,我们会选择将它加入到收藏夹中,但是网站一旦过期,以后就看不到这个网页了.当然也可以将网页打印成PDF文档保存.最新的Windows 10中的Edge浏览器支持将网页 ...

  10. Error Handling in ASP.NET Core

    Error Handling in ASP.NET Core 前言  在程序中,经常需要处理比如 404,500 ,502等错误,如果直接返回错误的调用堆栈的具体信息,显然大部分的用户看到是一脸懵逼的 ...