HackerRank: Spanning Tree Fraction 题解
题目:https://www.hackerrank.com/contests/w31/challenges/spanning-tree-fraction 一张连通图G=(V,E)上,每条边有a和b两个整数,求一个生成树使得Sum(a) / Sum(b) 最大,输出这个最大值的分数形式 p/q
设 \(\frac{\sum{a\_i}}{\sum{b\_i}} \ge
c\) ,经过变换可得,\(\sum{(a\_i - b\_i
c)} \ge 0\),这种形式下 ai - bi * c
就退化为一条边的
cost,能方便得用 Prim 或 Kruskal 算法求出 cost 最大的生成树。
因为我们知道 c 的取值是受限制的——显然不能任意大。根据题意,我们要求 c
的最大可能值 max(c),借助二分查找:如果 c 取值 (L+R)/2
时找不到生成树满足 sum cost >= 0,说明 max(c) 在右半边;反之,如果 c
的取值 (L+R)/2
时可行,说明在左半边(因为 C
是实数,这里说的都是闭区间)。
Prim 和 Kruskal 算法的实现也是一个难点。本题中 Kruskal 算法更简单,从小到大取所有的边,利用并查集可以快速判断这条边是否已经被连通了,若还为连通就要选取此边。
最后的 p/q 怎么求呢?显然从实数 c 变回 p/q 是不可能的。假如循环 N 次,最后一次循环可以认为已经收敛了,最后一次计算中途的 \(\sum{a\_i}\) 和 \(\sum{b\_i}\) 就是最优 case 下的取值,将 \(\frac{\sum{a\_i}}{\sum{b\_i}}\) 化简、消除公约数即可。
1 |
|