给出一个 n n n 个点 m m m 条边的无向图,第 i i i 条边有两个权值 a i a_i ai和 b i b_i bi 求该图的一棵生成树 T T T ,使得( ∑ a e ) ∗ ( ∑ b e ) \sum a_e)*(\sum b_e) ∑ae)∗(∑be)最小。
https://www.luogu.org/problemnew/solution/P5540
把 ∑ a e \sum a_e ∑ae看作 x x x, ∑ b e \sum b_e ∑be看作 y y y,答案就变成了平面上的一个坐标点 ( x , y ) (x,y) (x,y)。这样平面上最多一共有 n n − 2 n^{n-2} nn−2个点(生成树的个数),现在要求出一个点使得 x × y x\times y x×y最小。很容易想到答案在凸包的左下角上,现在就是想办法求出该点。
如果点 A A A是 x x x最小的点, B B B是 y y y最小的点,那么点 A A A和点 B B B一定是在凸包上。假设点 C C C是在 A B AB AB的左下处,那点 C C C一定更优,所以我们要找到点一个在 A B AB AB左下处的点 C C C使得三角形 A B C ABC ABC面积最大,或者 A B × A C AB\times AC AB×AC最小。这样求出来的点 C C C也是在凸包上的。
推一下式子: A B × A C = ( x B − x A ) y C + ( y A − y B ) x C − ( x B − x A ) y A + ( y B − y A ) x A AB\times AC=(x_B-x_A)y_C+(y_A-y_B)x_C-(x_B-x_A)y_A+(y_B-y_A)x_A AB×AC=(xB−xA)yC+(yA−yB)xC−(xB−xA)yA+(yB−yA)xA
后面两项是常数,所以我们只要让 ( x B − x A ) y C + ( y A − y B ) x C (x_B-x_A)y_C+(y_A-y_B)x_C (xB−xA)yC+(yA−yB)xC最小即可。对此我们只要对每条边设一个权值为: ( x B − x A ) a [ i ] + ( y A − y B ) b [ i ] (x_B-x_A)a[i]+(y_A-y_B)b[i] (xB−xA)a[i]+(yA−yB)b[i],跑一边最小生成树就可以求出点 C C C。
求出来点 C C C后,只需要递归求在 A C AC AC和 C B CB CB左下方的点即可。
因为一张 n n n个点的图,凸包上的点数期望是 ln n \sqrt{\ln n} lnn ,我们最多有 n n − 2 n^{n-2} nn−2个点,所以最后的复杂度是 O ( m l o g ( m ) ln n n − 2 ) O(mlog(m)\sqrt{\ln n^{n-2}}) O(mlog(m)lnnn−2 )