很久很久以前,森林里住着一群兔子。兔子们无聊的时候就喜欢研究星座。如图所示,天空中已经有了 n 颗星星,其中有些星星有边相连。兔子们希望删除掉一些边,然后使得保留下的边仍能是 n 颗星星连通。他们希望计算,保留的边的权值之和最小是多少?
输入
第一行只包含一个表示星星个数的数 n,n 不大于 26,并且这 n 个星星是由大写字母表里的前 n 个字母表示。接下来的 n-1 行是由字母表的前 n-1 个字母开头。最后一个星星表示的字母不用输入。对于每一行,以每个星星表示的字母开头,然后后面跟着一个数字,表示有多少条边可以从这个星星到后面字母表中的星星。如果 k 是大于 0,表示该行后面会表示 k 条边的 k 个数据。每条边的数据是由表示连接到另一端星星的字母和该边的权值组成。权值是正整数的并且小于 100。该行的所有数据字段分隔单一空白。该星星网络将始终连接所有的星星。该星星网络将永远不会超过 75 条边。没有任何一个星星会有超过 15 条的边连接到其他星星(之前或之后的字母)。在下面的示例输入,数据是与上面的图相一致的。
输出
输出是一个整数,表示最小的权值和。
样例输入
1 2 3 4 5 6 7 8 9
9 A2 B 12 I 25 B3 C 10 H 40 I 8 C2 D 18 G 55 D1 E 44 E2 F 60 G 38 F0 G1 H 35 H1 I 35
样例输出
1
216
提示
考虑看成最小生成树问题,注意输入表示。
思路
这道题是一个最小生成树的问题,我们可以用 Prim 算法来解决,默认从 A 开始,然后不断更新最小生成树,更新的办法就是先找到一个点,然后找到这个点到未访问的、可到达的顶点的权值。若出现比之前更小的权值,则要修改,否则,不用,最后标记这个点已访问,后面就是重复这个过程,直到所有的点都被访问。
intfindMin(){ int res = INT_MAX, id; for(int i = 0; i < 26; ++i) { if(isSelect[i] == false && res > weight[i]) { res = weight[i]; id = i; } } return id; }
intfindMin(){ int res = INT_MAX, id; for(int i = 0; i < 26; ++i) { if(isSelect[i] == false && res > weight[i]) { res = weight[i]; id = i; } } return id; }