最小生成树
Posted yiyiyizqy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了最小生成树相关的知识,希望对你有一定的参考价值。
最小生成树有两种算法:
1、prim算法
2、kruskal算法
老师主要给我们讲了第二种算法。最小生成树是包含原图中的所有 n 个结点,并且有保持图连通的最少的边。也就是边权之和最小,并且可以联通所有点的无环图。
1、按边权进行排序
2、找出边权最小的边,如果它们不在一个集合(无环),那就加入最小生成树的集合中。
3、不符合条件就继续找。
4、直到找出n-1条边为止。
为什么要无环呢,因为形成环以后,即使不用这条边,整个图也是能够联通的,所以说这条边是不必要的。排在前面把整个图联通起来的边必定是最短的,是最优的选择。
但是要注意,在合并最小生成树时,是把它们的祖先合并,并不是两个数合并。这可是个大错误!!!
参考代码——
struct ee{ int to; int from; int l; }f[10005]; bool cmp(ee x,ee y) { return x.l<y.l; }//排序 int finda(int x) { if(father[x]==x) return x; return father[x]=finda(father[x]); } int main() { freopen("1592.in","r",stdin); freopen("1592.out","w",stdout); cin>>n; for(int i=1;i<=n;i++) father[i]=i; for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { cin>>a; if(a==0) continue; else { e++; f[e].from=i; f[e].to=j; f[e].l=a; } } } sort(f+1,f+1+e,cmp); int ans=0; for(int i=1;i<=e;i++) { if(finda(f[i].from)!=finda(f[i].to))//判断是否在同一个并查集里 { ans+=f[i].l; father[finda(f[i].from)]=finda(f[i].to);//合并祖先 } } cout<<ans<<endl; return 0; }
以上是关于最小生成树的主要内容,如果未能解决你的问题,请参考以下文章