UTPC 2013 F - 魔法の糸
解説を見てACしたのだが、実装でつまづいた……というか、計算量がよくわかっていなかったのでメモ。
頂点pを含む連結成分V(p)と頂点qを含む連結成分V(q)を併合するとき、V(p)とV(q)の間の辺をどう集めるかが問題になるが、重みを隣接行列にでも記録しておいて、単にV(p)の頂点とV(q)の頂点のペアを総当たりすればよい。こうすると、この部分の計算量がQ回の更新でO(N2Q)になってしまいそうな気がしていたのだが、よく見ると1つの頂点ペア{v,w}につき高々1回しか処理されていないので、O(N2+Q)で済んでいる。
全体の計算量について。Kruskal法の前に辺の長さでソートする部分がボトルネックになる。頂点p, qを結ぶi個目のクエリに対して、V(p),V(q)の間の辺がdi本あったとすると、上で述べたようにd1+...+dQ≤Mである。また、以前のクエリでV(p)の最小全域木を作ろうとした時に選んだ辺は高々∣V(p)∣であり、V(q)についても同様に∣V(q)∣である。∣V(p)∣+∣V(q)∣≤Nだから、i個目のクエリで扱うべき辺の数は高々N+di本となる。したがって、Q回のソートの計算量は
==⊆⊆O(i=1∑Q(N+di)log(N+di))O(i=1∑Q(N+di)logN)O(i=1∑QNlogN+i=1∑QdilogN)O(QNlogN+MlogN)O((N2+M)logN).
ソートの部分はバケットソートでも通って計算量はO(N2+M+Qmaxwi)となる……けど、別に速くはならない。