DGZX1522 - 并查集在kruskal中的应用
并查集的简单应用。
Kruskal是求最小生成树的经典算法之一,如果忘记了,先做一下DGZX1042。
Kruskal中每次挑选一条边加入最小生成树,就相当于将该边两个端点所在集合合并。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
using namespace std;
int pa[3001];
int rank[3001];
int n, m;
int ans;// answer
int tot;// total
struct node{ int x, y, z; };
node tn[50000];
int cmp(const void *pa, const void *pb)
{
node *na = (node*)pa;
node *nb = (node*)pb;
return na->z - nb->z;
}
int Find(int x)
{
int y = x;
while (pa[y]!=0)// 寻找根
{
y = pa[y];
}
int root = y;// 保存根
int w;
y = x;// 复位
while (pa[y]!=0)// 执行路径压缩
{
w = pa[y];
pa[y] = root;
y = w;
}
return root;
}
void Union(int x, int y, int w)
{
int u = Find(x), v = Find(y);
if (u==v) return;
if (rank[u]<=rank[v])
{
pa[u] = v;
if (rank[u]==rank[v])// 树高相等时,合并后树会长高
rank[v]++;
}
else
{
pa[v] = u;
}
tot++; ans += w;
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=0; i<m; i++)
scanf("%d%d%d",&tn[i].x,&tn[i].y,&tn[i].z);
for (int i=1; i<=n; i++)// 各个子树高度初始化为 1
rank[i] = 1;
qsort(tn,m,sizeof(node),cmp);
for (int i=0; i<m; i++)
{
Union(tn[i].x,tn[i].y,tn[i].z);
if (tot==n-1) break;
}
printf("%d\n", ans);
return 0;
}

浙公网安备 33010602011771号