最小生成树
作用
求最小的连接所有点所需要的边的长度的总和。
如在下图中,连接沿着绿色路线连接 A , B , C , D , E , F , G A, B, C, D, E, F, G A,B,C,D,E,F,G 七点所需要的边的长度的总和最小。
实现
前缀知识:并查集,算法:贪心
1. 将路径按照从短至长进行排序
2. 取出目前最短的一条路径,如果他们两个不在一个集合中,即两点没有被连接,最小值加上路径长度且合并两个集合,否则不做任何事,直到遍历完整个列表。
代码实现
Example: 一本通1349-最优布线问题
变量用途
struct node { int me, e, v; }; // 存储一条路线的起点、终点、权值
int ans, g[110];
// ans -> 最终答案 | g -> 并查集
并查集
int find(int x) { return (g[x] == x) ? (x) : (g[x] = find(g[x])); }
重点:最小生成树
void f()
{
std::sort(v.begin(), v.end(), [](node a, node b) { return a.w < b.w; }); // 步骤 1
while (v.size())
{
node p = v.front();
if (find(p.me) != find(p.e))
ans += p.w, g[find(p.e)] = find(p.me); // 步骤 2
v.pop_front();
}
}
主函数
int n, k;
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n && scanf("%d", &k); j++)
if (j > i) // 去除重复信息
v.push_back({i, j, k}); // 加入到路线列表
for (int i = 1; i <= n; i++)
g[i] = i; // 初始化并查集
f(); // 进行最小生成树操作
printf("%d", ans); // 输出答案
return 0;
}