【模板】最小生成树
题目描述
如题,给出一个无向图,求出最小生成树,如果该图不连通,则输出 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>
using namespace std;
int n, m;
int x, y, z;
const int N = 2e5 + 50;
struct E
{
int u;
int v;
int w;
}e[N];
bool cmp(const E &a, const E &b)
{
return a.w < b.w;
}
int fa[N];
int cnt, res;
int find(int x)
{
if(fa[x] == x) return x;
return fa[x] = find(fa[x]);
}
bool k()
{
sort(e, e + m, cmp);
for(int i = 1; i <= n; i++)
fa[i] = i;
for(int i = 0; i < m; i++)
{
int x = find(e[i].u);
int y = find(e[i].v);
if(x != y)
{
fa[x] = y;
res += e[i].w;
cnt++;
}
}
return cnt == n - 1;
}
int main()
{
scanf("%d %d", &n, &m);
for(int i = 0; i < m; i++)
{
scanf("%d %d %d", &x, &y, &z);
e[i] = {x, y, z};
}
if(k()) printf("%d", res);
else puts("orz");
return 0;
}