某个乡镇要搞"村村通网":一共有 n 个村子,任意两个村子之间都可以架设一条光缆,但造价各不相同 —— 有的隔着一条河,贵;有的只隔一片田,便宜。乡长的要求很简单:让所有村子都能互相通信,总造价最低。
请你先回答第一个问题:最少需要架设几条光缆?答案是 n − 1 条。因为 n 个点要用边连成一个整体,至少 n − 1 条边;而 n − 1 条边恰好能把它们连成一棵"树",任何一条多余的边都会造成环路、白花钱。
第二个问题:怎么挑这 n − 1 条边?承包商老张的做法是"先把所有可能的线路按造价从低到高排个队,从最便宜的看起:只要这条线路连接的是两个还没打通的区域,就签下它;如果它连接的两个村子本来就在同一片已打通的区域里(会形成环),就跳过。" —— 这叫 Kruskal 算法,它的目光始终盯在"边"上。
另一位工程师老李的做法不同:他从乡政府所在的村子开始,把"已经连进来的村子"画成一个圈,然后每次从圈内到圈外挑一条最便宜的线路,把圈外的那个村子拉进来,圈子越来越大,直到圈住所有村子 —— 这叫 Prim 算法,它的目光始终盯在"点"上。
两人算出的总造价完全一样(都是最小生成树),但工作量不同:村子多、线路稀疏时老张更快;村子少、线路密得像张网时老李更划算。
最小生成树 = 用最少的边连起所有点,且总权值最小。
💡 故事背后的算法思想
最小生成树是贪心算法在图上最漂亮的胜利之一:每一步都做"局部最优"的选择(当前最短的边 / 当前最短的跨界边),最终却能得到全局最优解。
两种算法的"贪心方式"不同,但都建立在同一个数学性质上:割性质 —— 对于图的任意一种把点分成两半的划分(割),横跨这个割的最小边一定属于某棵最小生成树。Kruskal 与 Prim 只是从不同角度反复应用这一性质。
记住一句话:Kruskal 选边,Prim 选点;稀疏图用 Kruskal,稠密图用 Prim。