一、题目链接
二、题目分析
(一)算法标签
最小生成树 Kruskal
(二)解题思路
三、AC代码
解法一:
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
const int N = 2021;
LL ans = 0;
int cnt = 0;
struct Edge {
int a, b, w;
bool operator< (const Edge& e) const
{
return w < e.w;
}
}edges[N * N / 2];
// 计算边权
int cost(int a, int b)
{
int res = 0;
while (a || b)
{
int x = a % 10;
int y = b % 10;
if (x != y) res += x + y;
a /= 10;
b /= 10;
}
return res;
}
int p[N];
int find(int x)
{
if (p[x] != x) p[x] = find(p[x]);
return p[x];
}
// 将a,b所在的集合合并
void merge(int a, int b)
{
a = find(a), b = find(b);
p[a] = b;
}
LL kruskal()
{
// 初始化并查集
for (int i = 1; i <= N; i ++ )
p[i] = i;
// 按边权从小到大排序
sort(edges, edges + cnt);
// 遍历每条边,如果不连通(不在一个集合),则合并a,b所在的两个集合
LL res = 0;
int num = 0;
for (int i = 0; i < cnt; i ++ )
{
int a = edges[i].a, b = edges[i].b, w = edges[i].w;
if (find(a) != find(b))
{
merge(a, b);
num ++ ;
res += w;
}
}
if (num < N - 1) return 0x3f3f3f3f;
return res;
}
int main()
{
for (int i = 1; i <= N; i ++ )
for (int j = i + 1; j <= N; j ++ )
edges[cnt ++ ] = {i, j, cost(i, j)}; // 两个点之间存一条边即可
ans = kruskal();
printf("%lld", ans); // 4046
return 0;
}
四、其它题解
城邦 【第十二届蓝桥杯省赛第二场C/C++】【最小生成树】1
城邦 【第十二届蓝桥杯省赛第二场C/C++】【最小生成树】2
Prim