【比赛日志】JOISC2020 Day2
JOI Day2
joitter2
这一题似乎有点思路?
等价于:如果有\((x,y)\),且有\((y,z),(z,y)\),则有\((y,z)\)。
(显然可以直接在新图上修改,得到的图再进行操作)
考虑在原图中加一条边\((x,y)\):
- 若\((x,y)\)存在,则不操作。
- 若\((y,x)\)存在,则新增了一条双向边:
- 对所有连向\(x\)或\(y\)的点,它们此时都同时连向了\((x,y)\)。
- 在这之前,如果有\((y,z)\)与\((z,x)\),那么新增的\((z,y)\)与\((y,z)\)形成新的双向边。
假设此时的图已经是最简形式,若\((x,y)\)产生了双向边,这么处理:
将\(x,y\)缩成一个点\(x\),将所有连向\(y\)的和\(y\)连出的边移动到\(x\)上,将siz[x] += siz[y]
。
考虑什么时候可能形成新的双向边:由于原图不存在双向边,发现只有在存在\(z\),且有\((y,z)\)与\((z,x)\)或\((z,y)\)与\((x,z)\)时才会增加,在移动的时候顺便判断一下即可。
如果用set
维护,合并时用启发式合并的话,复杂度应该是\(O(n\log^2 n)\)的。
……等下,好像这个做法是错误的……因为\((x,y),(y,x),(a,b),(b,a),(x,a)\)却不一定有\((y,a)\)。
不过这个性质是对的:如果\((x,y)\)且\((y,z_1),(z_2,z_3),\ldots,(z_{k-1},z_k)\)两两可达,那么有\((x,z_i)\)。反过来也成立。
设一个极大的两两有双向边相连的的点集为一个“大点”,则最终的所有边可以用一些小点连向大点的边刻画。
若两个大点\(X,Y\)中,有\(x\in X, y\in Y\)使得有边\((x,Y),(y,X)\),则可以将\(X,Y\)合并成一个新的大点。
对每一个小点,维护所属的大点与连出的大点;对每一个大点,维护连进的小点以实现边的转移。在修改时,需要查询在目标大点\(Y\)中,存不存在\(y\)连向目前的大点,需要额外维护每一个大点连向了哪些大点。
……这玩意有点细节……自闭了……
来具体描述一下如何操作吧:
1.