(最小生成树)Kruskal算法
算法要点:Kruskal算法的最难点在于怎样判断加入边(x, y)后是否形成了环.
问题可化简为:判断边(x, y)的两个顶点在图(实际是森林)mst中是否已连通。如果已经连通,加入边将形成环;
否则,不形成环。
Kruskal算法中, 要用到并查集的合并与查找。
完整代码如下:(具体见代码注释)
1 #include<bits/stdc++.h> 2 using namespace std; 3 int fa[1000010]; 4 int n, m; 5 int sum = 0; 6 struct node 7 { 8 int x, y; 9 int v; 10 }e[10001000]; 11 bool mycmp(node a, node b) 12 { 13 return a.v < b.v; 14 } 15 int getfa(int k)//找到祖先(最高级祖先) 16 { 17 if(k == fa[k]) return k; 18 fa[k] = getfa(fa[k]); 19 return fa[k]; 20 } 21 void merge(int x, int y)//合并x, y 22 { 23 int fx = getfa(x); 24 int fy = getfa(y); 25 fa[x] = fy; 26 } 27 bool judge(int x, int y)//判断是否在一个并查集中 28 { 29 int fx = getfa(x); 30 int fy = getfa(y); 31 return (fx == fy); 32 } 33 int main() 34 { 35 //freopen("input.in","r",stdin); 36 //freopen("output.out","w",stdout); 37 scanf("%d%d",&n); 38 for(int i = 1;i < n;i++) 39 scanf("%d%d%d", &e[i].x, &e[i].y, &e[i].v); 40 for(int i = 1; i <= n; i++) fa[i] = i; //初始每个点都是一个集合 41 sort(e + 1, e + n + 1, mycmp); //边按升序排列 42 int cal = 0; 43 for(int i = 1;i <= n;i++) 44 { 45 int v = getfa(e[i].x); 46 int u = getfa(e[i].y);//寻找两个节点的祖先 47 if(v != u)//如果不在一个并查集中 48 { 49 merge(v, u); 50 sum += e[i].v;//最小生成树总长度 51 if(++cal == n - 1)//如果已经做了N - 1次 52 { 53 printf("%d\n", sum); 54 } 55 } 56 } 57 return 0; 58 }
原文地址:https://www.cnblogs.com/smilke/p/10758196.html
时间: 2024-10-04 02:48:16