#include<bits/stdc++.h>
#define LL long long
using namespace std;
struct node
{
int v, w;
};
const int N = 1e5 + 5, INF = 0x3f3f3f3f;
int n, m, s, cnt, ans, d[N], vis[N]; // d中的值是当前点到集合外任一点最近的距离
vector<node> G[N];
void prim(int s)
{
memset(d, 0x3f, sizeof(d));
d[s] = 0;
for (int i = 1; i <= n; i ++)
{
int u = 0;
for (int j = 1; j <= n; j ++)
if (d[j] < d[u] && !vis[j])
u = j;
vis[u] = 1;
ans += d[u];
if (d[u] != INF) // 这个判断不可以少 不能直接从 cnt ++ 可能到最后选出来的是无穷大的边
cnt ++;
for (int j = 0; j < G[u].size(); j ++)
{
int v = G[u][j].v, w = G[u][j].w;
d[v] = min(d[v], w);
}
}
}
int main()
{
cin >> n >> m >> s;
for (int i = 1; i <= m; i ++)
{
int u, v, w;
cin >> u >> v >> w;
G[u].push_back({v, w}), G[v].push_back({u, w});
}
prim(s);
return 0;
}
二. kruskal (稀疏图)
#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int N = 1e5 + 5;
struct node
{
int u, v, w;
bool operator < (const node & t) const
{return w < t.w;}
}e[N];
int n, m, s, cnt, ans, fa[N], vis[N];
vector<node> G[N];
int find(int x)
{
if (fa[x] == x)
return x;
return fa[x] = find(fa[x]);
}
bool kruskal()
{
sort(e + 1, e + m + 1);
for (int i = 1; i <= n; i ++)
fa[i] = i;
for (int i = 1; i <= m; i ++)
{
int x = find(e[i].u), y = find(e[i].v);
if (x != y)
{
fa[x] = y; // 改变的是 e[i].u 的父节点的父节点 才能把一整串全部改过去
// 而不是 fa[e[i].u] 只改变当前节点的父节点没有用
ans += e[i].w;
cnt ++;
}
}
return cnt == n - 1; // 判断能否构成最小生成树
}
int main()
{
cin >> n >> m >> s;
for (int i = 1; i <= m; i ++)
{
int u, v, w;
cin >> u >> v >> w;
G[u].push_back({v, w}), G[v].push_back({u, w});
}
kruskal();
return 0;
}