题意(形式化)
给定 nnn 个点,进行 mmm 次连边操作后进行 qqq 次询问,询问两个点 u,vu,vu,v 它们最早在第几次你连边操作后联通,如果至始至终没有联通,输出 −1-1−1。
思路
注意到如果 aaa 与 bbb 联通,且 bbb 与 ccc 联通,那么 aaa 肯定与 ccc 联通,相当于朋友的朋友是朋友,考虑并查集。
我原先的思路是每次合并连通块时,根节点存现在的操作数,但是后来发现这样会破坏原有的信息,于是在每次连边后需要一个新点来当两点的父节点,这个新点存联通时间。换句话说,这个新点存的是:“左子树所代表的连通块与右子树所代表的连通块,连通的最早时间。(注意每次连边都会需要一个新结点,所以实际上要用到 n+mn+mn+m
个结点)但是为了不破坏树原来的结构,我们无法进行路径压缩,这也导致了时间复杂度爆炸,无法通过。于是考虑我们在并查集的基础上新建个树,这个树才存未更改的情况,并查集则正常路径压缩。最后,如果我们想求两个结点何时联通,只需LCA查找其父节点即可(原因显然),需特判两个点为同一点以及两点不联通的情况。
后来我才知道原来这叫做Kruskal 重构树。当时为了不TLE重复尝试了15次,都快绝望了。
AC CODE