(模板)最小生成树(Krukal)
(模板)最小生成树(Kruskal)
题目描述
如题,给出一个无向图,求出最小生成树,如果该图不连通,则输出 orz。
输入格式
第一行包含两个整数 \(N,M\),表示该图共有 \(N\) 个结点和 \(M\) 条无向边。
接下来 \(M\) 行每行包含三个整数 \(X_i,Y_i,Z_i\),表示有一条长度为 \(Z_i\) 的无向边连接结点 \(X_i,Y_i\)。
输出格式
如果该图连通,则输出一个整数表示最小生成树的各边的长度之和。如果该图不连通则输出 orz。
样例 #1
样例输入 #1
4 5
1 2 2
1 3 2
1 4 3
2 3 4
3 4 3
样例输出 #1
7
提示
数据规模:
对于 \(20\%\) 的数据,\(N\le 5\),\(M\le 20\)。
对于 \(40\%\) 的数据,\(N\le 50\),\(M\le 2500\)。
对于 \(70\%\) 的数据,\(N\le 500\),\(M\le 10^4\)。
对于 \(100\%\) 的数据:\(1\le N\le 5000\),\(1\le M\le 2\times 10^5\),\(1\le Z_i \le 10^4\)。
样例解释:

所以最小生成树的总边权为 \(2+2+3=7\)。
代码
#include <bits/stdc++.h>
#define endl '\n'
struct Edge
{
int u, v, w;
}edge[200010];
bool cmp(Edge a, Edge b)
{
return a.w < b.w;
}
int pre[5050];
int find(int s)
{
if (pre[s] == s) return s;
return pre[s] = find(pre[s]);
}
void Merge(int a, int b)
{
int pre_a = find(a), pre_b = find(b);
pre[pre_b] = find(pre_a);
}
void kruskal()
{
int n = 0, m = 0;
std::cin >> n >> m;
for (int i = 1; i <= n; i++)
{
pre[i] = i;
}
for (int i = 1; i <= m; i++)
{
std::cin >> edge[i].u >> edge[i].v >> edge[i].w;
}
std::sort(edge + 1, edge + 1 + m, cmp);
int ans = 0, tot = 0;
for (int i = 1; i <= m; i++)
{
int preu = find(edge[i].u);
int prev = find(edge[i].v);
if (preu != prev)
{
tot++;
ans += edge[i].w;
Merge(edge[i].u, edge[i].v);
}
}
if (tot == n - 1)
{
std::cout << ans << endl;
}
else
{
std::cout << "orz" << endl;
}
}
int main()
{
kruskal();
return 0;
}

浙公网安备 33010602011771号