1. 项目概述
公路修建问题是一个经典的图论应用场景,源自洛谷P1265题目。这个问题要求我们在给定多个城市坐标的情况下,规划一个总长度最短的公路网络,使得任意两个城市之间都可以互相到达。这实际上就是图论中的最小生成树(Minimum Spanning Tree, MST)问题在实际工程中的应用。
我第一次接触这个问题是在参加算法竞赛训练时,当时就被它简洁的题干和丰富的解题思路所吸引。不同于纯理论的最小生成树算法题目,这道题将抽象概念具象化为公路修建场景,让算法学习变得更加生动有趣。在实际操作中,我们需要处理城市坐标计算、距离矩阵构建、最小生成树算法选择等一系列技术环节。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 核心算法解析
2.1 最小生成树基础概念
最小生成树是指在一个带权无向图中,找到一棵包含所有顶点的生成树,并且所有边的权值之和最小。对于公路修建问题,我们可以将每个城市看作图中的一个顶点,城市之间的距离作为边的权重。
在解决这个问题时,最常用的两种算法是:
- Prim算法:从一个顶点开始,逐步扩展生成树,每次添加与当前树相连的最短边
- Kruskal算法:按边权从小到大排序,逐步添加不形成环的边
2.2 算法选择与优化
对于公路修建问题,由于我们需要计算所有城市两两之间的距离,这本质上是一个完全图。在这种情况下,Prim算法(特别是使用优先队列优化的版本)通常更为高效。
Prim算法的时间复杂度:
- 朴素实现:O(V²)
- 使用优先队列优化:O(E + VlogV)
由于题目中城市数量可能达到5000个,我们必须选择优化后的实现方式。以下是使用优先队列优化的关键步骤:
cpp复制priority_queue<pair<double, int>, vector<pair<double, int>>, greater<pair<double, int>>> pq;
vector<bool> visited(n, false);
double total_length = 0;
// 从城市0开始
pq.push({0.0, 0});
while (!pq.empty()) {
auto [dist, u] = pq.top();
pq.pop();
if (visited[u]) conti
