最小生成树模板
Posted guaguastandup
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了最小生成树模板相关的知识,希望对你有一定的参考价值。
这是一个愉快的敲模板的过程
昨晚不知道为啥老是RE,结果改着改着,竟然本来能ac的几个数据开始WA了.........
啊哈哈哈哈哈啊哈哈哈
好吧
这个是kruskal算法
贪心策略:n个节点的最小生成树里面包含了n-1条边,这n-1条边是不可以成环的,这样就可以保证联通了,所以我们只要把这n-1条边选出来,因为是最小生成树,所以我们要找最小的权边
所以基本的思路就定了:
存边
按照权值将这些边排序
排序完了开始遍历,决定把谁加入MST
判断的条件是:是否成环,成环的话就不要,不成环的话就加入MST
接下来要解决的问题就是怎么判断成环->利用并查集,共祖->成环
共祖在某种意义上就等于联通
所以有一个查的过程和并的过程
代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int N=5020; 5 const int F = 2e5 + 100; 6 struct node{ 7 int u, v, c; 8 } e[F]; 9 int f[N],cnt,sum; 10 int find(int x){ 11 return f[x] == x ? x : f[x] = find(f[x]);} 12 bool unionset(int a,int b){ 13 a = find(a),b = find(b); 14 if(a!=b){ 15 f[b] = a; 16 return true; 17 } 18 return false; 19 } 20 bool cmp(node a,node b){ 21 return a.c < b.c; 22 } 23 int main(){ 24 int n, m; 25 scanf("%d%d", &n, &m); 26 for (int i = 1; i <=m;i++){ 27 scanf("%d%d%d", &e[i].u, &e[i].v, &e[i].c); 28 } 29 sort(e + 1, e + 1 + m, cmp); 30 for (int i = 1; i <= n;i++) 31 f[i] = i; 32 for (int i = 1; i <= m;i++){ 33 if(unionset(e[i].u,e[i].v)){ 34 cnt++; 35 sum += e[i].c; 36 } 37 if(cnt==n-1) 38 break; 39 } 40 printf("%d",sum); 41 //system("pause"); 42 return 0; 43 }
下面是prim代码
以上是关于最小生成树模板的主要内容,如果未能解决你的问题,请参考以下文章