题意:
给出集合U,V,集合U有n个元素,集合V有m个元素;
有 m 个操作,mi : s1 s2 有一条s1指向s2的边(s1,s2可能属于第三个集合,暂且称之为K集合);
指向边具有传递性,即 A->B,B->C <=> A->C
求V集合中被 U 指向的元素;
题解:
并查集debug个了两天,始终wa,今天上午上数字逻辑课的时候,灵光一闪,又想到了一个可能会出错的点;
经过一番挣扎,终于判断了此题不能用并查集做,蓝瘦香菇~~~~~~
还记得并查集中的Union(x,y)操作吗?
此函数得作用是将 x元素 所在的集合与 y元素 所在得集合合并成一个大集合;
对于此题,初始想法是,并查集中只保存
①U 集合指出去的边
②K 集合指向 V 集合的边
③V 集合指向 V 集合的边
如果满足上述三种条件,则Union(s1,s2);
最后,判断V集合中元素的Find(s)是否属于U集合,如果属于,则输出s;
那么,问题来了,s1,s2真的可以这么合并吗?
看如下连接方式:
输入的顺序是:
v2 v1
k2 v1
对于第一条指令,Union(v2,v1)是没得说的,此时 fa(v1) = v2 , fa(v2) =v2;
对于第二条指令,可以调用 Union(k2,v1) 吗?
先看看调用后的结果:Find(k2) = k2 , Find(v1) = v2 , k2 ≠ v2 , fa(v1)=fa(v2)=k2; ???
那么,再加入一条边呢?
u1 k2
那么,此时调用Union(u1,k2) : fa(k2) = u1;
当输出时:
v1 : Find(v1) = Find(k2) = u1 ,输出 v1
v2 : Find(v2) = Find(k2) = u1 ,输出 v2
这就出现问题了吧!!!
那,如果人为的将 fa(v1) = k2,但是fa(v2) = v2呢?
看一下接下来的这张图:
加入边 u2 v2
输出时:
v1 : Find(v1) = k2 ,不输出 v1
v2 : Find(v2) = u2 ,输出 v2
又出现错误了,是吧!
为什么并查集会出现这个问题呢?
v1,v2属于同一个集合,v1,k2属于同一个集合,但 k2,v2并不能属于同一个集合,所以不能合并;
看来,当图是有向图时,慎用并查集!!!!!!!!!!!!!
所以说,还是搜索大法好!!!!
AC代码:
1 #include 2 #include 3 #include
View Code