最小生成树[模板]
题目描述
如题,给出一个无向图,求出最小生成树,如果该图不连通,则输出 orz。
输入格式
第一行包含两个整数
N
,
M
N,M
N,M表示该图共有
N
N
N个结点和
M
M
M条无向边。
接下来 M M M行每行包含三个整数 X i , Y i , Z i X_i,Y_i,Z_i Xi,Yi,Zi,表示有一条长度为 Z i Z_i Zi的无向边连接结点 X i , Y i X_i,Y_i Xi,Yi。
输出格式
如果该图连通,则输出一个整数表示最小生成树的各边的长度之和。如果该图不连通则输出orz。
输入输出样例
输入
4 5
1 2 2
1 3 2
1 4 3
2 3 4
3 4 3
输出
7
数据规模
对于 100 % 100\%% 100% 的数据: 1 ≤ N ≤ 5000 1\le N\le 5000 1≤N≤5000, 1 ≤ M ≤ 2 × 1 0 5 1\le M\le 2\times 10^5 1≤M≤2×105
K r u s k a l Kruskal Kruskal算法
首先,最小生成树就是在一个有
N
N
N个点的连通图中取
N
N
N-
1
1
1条边,使得这
N
N
N-
1
1
1条边的权值和最小
而求最小生成树有两种算法:
K
r
u
s
k
a
l
Kruskal
Kruskal和
P
r
i
m
Prim
Prim算法,而我们这里先讲
K
r
u
s
k
a
l
Kruskal
Kruskal
K
r
u
s
k
a
l
Kruskal
Kruskal其实很容易理解,就是不断的选取最小边,前提是这条边的两个点之前是未连通的,这样我们就很轻松的用并查集做就行了
代码展示
K r u s k a l Kruskal Kruskal的代码十分简单,34行代码十分清爽
#include<bits/stdc++.h>
using namespace std;
struct node
{
int x,y,val;
}a[200010];
int n,m,ans;
int f[5010];
bool Cmp(node x,node y)
{
return x.val<y.val;
}
int find(int x)
{
return f[x]==x?x:f[x]=find(f[x]);
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].val);
sort(a+1,a+m+1,Cmp);
for(int i=1;i<=n;i++)f[i]=i;
for(int i=1;i<=m;i++)
{
if(find(a[i].x)!=find(a[i].y))
{
ans+=a[i].val;
f[f[a[i].x]]=f[a[i].y];
}
}
printf("%d\n",ans);
return 0;
}