- 1、本文档共130页,可阅读全部内容。
- 2、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
- 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
查看更多
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 例3 食物链(NOI2001) 通过上面的分析,并查集在本题中的运用已经呼之欲出。 一个集合有三类的元素,合并集合的时候,需要对三类元素进行合并。 Parity(ceoi99) 有一个01序列,长度=1000000000,现在有n条信息,每条信息的形式是-a b even/odd。表示第a位到第b位元素之间的元素总和是偶数/奇数。 你的任务是对于这些给定的信息,输出第一个不正确的信息所在位置-1。信息的数目不超过5000。 如果信息全部正确,即可以找到一个满足要求的01序列,那么输出n。 Parity(ceoi99) 输入文件 第一行一个整数m表示01序列的长度,第二行一个整数n表示信息的数目。 接下来是n条信息 样例输入 10 5 1 2 even 3 4 odd 5 6 even 1 6 even 7 10 odd 样例输出 3{因为第4个信息是不正确的,所以输出3,表示从1到3条信息都是正确的} Parity(ceoi99) 从整个01序列肯定是无法入手的,因为它的长度高达109。 从范围比较小的n入手。也就是说我们需要对信息进行一些特殊的处理。 a b even/odd,那么将元素b指向a-1,边的权值是even/odd。 下面我们由样例来说明一下这个处理方法。 Parity(ceoi99) 0 4 2 6 1 2 even 3 4 odd 5 6 even 1 6 even 0 1 0 0??? Parity(ceoi99) 显然在第4条信息加入的时候,6到0已经有值存在,即(0+1+0)mod 2=1,这时添入6到0为0显然是不对。 实现的时候不用开1-109的数组,因为出现的不同元素最多有104而已,因此,开一个列表存储元素即可。 算法的大致框架就是对于读入的信息不断地用上述方法处理,由区间的递推性质可以得出矛盾与否。 上述算法的实现就用到了并查集。 Disjoint Sets小结 先从问题的简单做法入手,构造出原始模型。 如果原始模型是对于集合之间合并处理问题,那么就可以使用并查集使得程序变得高效。 并查集的路径压缩只有在元素之间的特性存在递推关系时才可以使用。 * * * * * * * * * * * * * * * * * * * * * * * * * Disjoint Sets 并查集是一种树型的数据结构,用于处理一些不相交集合的合并问题。 并查集的主要操作有 1-合并两个不相交集合 2-判断两个元素是否属于同一个集合 3-路径压缩 元素的合并图示 1 3 2 4 5 合并1和2 合并1和3 合并5和4 合并5和3 判断元素是否属于同一集合 用father[i]表示元素i的父亲结点,如刚才那个图所示 1 2 3 5 4 faher[1]=1 faher[2]=1 faher[3]=1 faher[4]=5 faher[5]=3 判断元素是否属于同一集合 由此用某个元素所在树的根结点表示该元素所在的集合 判断两个元素时候属于同一个集合的时候,只需要判断他们所在树的根结点是否一样即可 也就是说,当我们合并两个集合的时候,只需要在两个根结点之间连边即可 并查集的操作 判断两个节点是否在同一个集合中 合并两个集合 并查集操作的关键——维护并查集 1 2 3 5 6 4 8 7 10 判断5与10是否在同一个集合中 第一步:上溯 11 第二步:上调 4 10 8 7 合并11和10所在的集合 第一步:上溯 第二步:合并 第三步:上调 路径压缩 上述的做法是指就是将元素的父亲结点指来指去的在指,当这课树是链的时候,可见判断两个元素是否属于同一集合需要O(N)的时间,于是路径压缩产生了作用 路径压缩实际上是在找完根结点之后,在递归回来的时候顺便把路径上元素的父亲指针都指向根结点 路径压缩示意图 1 3 2 4 5 由此我们得到了一个复杂度只是O(1)的算法 程序清单 function getfather(v:integer):integer; begin if (father[v]=0) then getfather:=v else begin father[v]:=getfather(father[v]); getfather:=father[v]; end; end; 程序清单 function judge(x,y:in
文档评论(0)