题目描述
如题,给出一个无向图,求出最小生成树,如果该图不连通,则输出orz
输入输出格式
输入格式:第一行包含两个整数N、M,表示该图共有N个结点和M条无向边。(N<=5000,M<=200000)
接下来M行每行包含三个整数Xi、Yi、Zi,表示有一条长度为Zi的无向边连接结点Xi、Yi
输出格式:输出包含一个数,即最小生成树的各边的长度之和;如果该图不连通则输出orz
输入输出样例
说明
时空限制:1000ms,128M
数据规模:
对于20%的数据:N<=5,M<=20
对于40%的数据:N<=50,M<=2500
对于70%的数据:N<=500,M<=10000
对于100%的数据:N<=5000,M<=200000
样例解释:
所以最小生成树的总边权为2+2+3=7
// Kruskal 并查集
#include <bits/stdc++.h>
using namespace std;
const int maxn = 5005;
const int maxm = 200020;
struct node
{
int x, y, c;
} e[maxm];
bool cmp(const node& a, const node& b)
{
return a.c < b.c;
}
int p[maxn];
int Find(int x)
{
if (p[x] == x)
return x;
return p[x] = Find(p[x]);
}
int main()
{
int n, m;
scanf("%d %d", &n, &m);
for (int i = 1; i <= m; i++)
scanf("%d %d %d", &e[i].x, &e[i].y, &e[i].c);
sort(e + 1, e + m + 1, cmp);
for (int i = 1; i <= n; i++)
p[i] = i;
int sz = 0;
int ans = 0;
for (int i = 1; i <= m; i++)
{
int fx = Find(e[i].x);
int fy = Find(e[i].y);
if (fx != fy)
{
p[fy] = fx;
sz ++;
ans += e[i].c;
}
}
if (sz == n - 1)
printf("%d\n", ans);
else
printf("orz\n");
return 0;
}
// Prim 堆优化
#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 10;
struct Edge {
int u, v;
long long w;
}e[maxn];
int n, m;
int f[maxn];
int Find(int x) {
if(x != f[x]) f[x] = Find(f[x]);
return f[x];
}
bool cmp(const Edge& a, const Edge& b) {
return a.w <b.w;
}
int main() {
scanf("%d%d", &n ,&m);
for(int i = 1; i <= m; i ++) {
scanf("%d%d%lld", &e[i].u, &e[i].v, &e[i].w);
}
sort(e + 1, e + 1 + m, cmp);
for(int i = 1; i <= n; i ++) {
f[i] = i;
}
long long ans = 0;
int sz = n;
for(int i = 1; i <= m; i ++) {
int fu = Find(e[i].u);
int fv = Find(e[i].v);
if(fu == fv) continue;
ans = ans + e[i].w;
sz --;
f[fu] = fv;
}
if(sz == 1) {
printf("%lld\n", ans);
} else {
printf("orz\n");
}
return 0;
}