前言
补题。
这个YL怎么天天都有人AK,这是一群什么神仙啊
中央集权(emperor)
终于出了一道裸题了 最小生成树
搞得我赶快复习了一下最小生成树的时间复杂度
Prim(堆优化):\(\text{O(m*logn)}\)
Kruskal(要并查集):\(\text{O(m*logm)}\)
权衡一下,选择 Prim+堆优化,能过 √
计算树(tree)
看完题解不觉说出了一声NB
首先从这棵树的角度上冥思苦想都没有什么好办法,最多树上倍增什么的,感觉行不通
然而我们还是考虑到了一点,树上两点间的的路径一般可以分为两块(设两点为 \(x\),\(y\))\(x->lca_{x,y}\) \(lca_{x,y}->y\)
以下我们就以 \(x\),\(y\) ,\(lca\) (\(lca_{x,y}\)简记为 \(lca\))做例子
我们不妨换一个角度,从 \(lca\) 与 \(x\) , \(y\) 的关系上考虑。这里我们引入根 \(z\) ,想到 \(lca->z\) 与 \(x-z\) 有一条共同的路径
(敲黑板) 前方高能!!!
我们把 \(x->lca\) 这条路径上值的变换记作一次变换,\(x->y\) 的变换由两个变换 \(x->lca->y\) 组成,变换的结果是一个值,这个值就如题意所述,是这条路径上的表达式值。\(x\)到其他结点的一次变换,结果可以用一个式子 \(ax+b\) 表示出来,\(a,b\) 是一个常数,\(x\) 就是 \(x\) 结点的值。
好的,理解上面这段话。接着看下面真正的高能环节
我们先预处理出树中每一个结点(\(x\))到根(\(z\))的变换结果,并将其变成 \(ax+b\) 的形式(保留a,b),同理还要预处理根到每个结点的变换
令 \((x->z)\) 的变换结果为 \(ax+b\) , \((lca->z)\) 的变换结果为 \(cx+d\),\(x->lca\) 的变换结果为 \(ex+f\)
\[∵c(ex+f) + d=ax+b\]
\[即 cex+cf+d=ax+b\]
\[∴ce=a,cf+d=b\]
\[∴e=\frac{a}{c},f=\frac{b+d}{c}\]
因为\(a,b,c,d\)均为已知的,故可以直接求得\(e,f\)
同理求 \((lca->y)\) 的变换。 令 \((z->y)\)为 \(ax+b\),\((z->lca)\)为\(cx+d\),\((y->lca)\) 为 \(ex+f\)
\[∵c(ax+b)+d=ex+f\]
\[∴e=ac,f=cb+d\]
本题到此解决。
据说要用什么Tarjan求LCA,这题有点卡常?先让我去学一下Tarjan求LCA再回来码代码