最小生成树Kruskal算法实现+快排实现权值排序

来源:互联网 发布:执行仪表板软件 编辑:程序博客网 时间:2024/06/17 03:50
要求要最少的边让图连通(任意两点之间可以互相到达)。要想让n个顶点的图连通,那么至少需要n-1条边。其实这里就是求一个图的最小生成树
基本思路:
首先按照边的权值进行排序按照升序,每次从剩余的边中选择权值较小且边的两个顶点不在同一个集合内的边(将所有的顶点放入一个并查集中,判断两个顶点是否连通,只需判断两个顶点是否在同一个集合中,即是否有共同的祖先,这样时间复杂度为O(logN))(就是不会产生回路的边),加入到生成树中,前提 就是每次都会判断各个顶点是否在各自的并查集中,直到加入了n-1条边为止。
Kruskal算法的时间复杂度:
对边进行快排O(MlogM),在m条边中找出n-1条边是O(MlogN),所有Kruskal算法的时间复杂度为O(MlogM+MlogN)。

通常M要比N大很多,因此最终时间复杂度为O(MlogM)。


#include<iostream>using namespace std;struct edgess{int p1;int p2;int weight;};int edge,point,po1,po2,w;int count=0;int sum=0;struct edgess edgs[10];int uni[10];void quiksort(int left,int right){if (right-left<=0){return;}if (right-left==1){if (edgs[left].weight>edgs[right].weight){swap(edgs[left],edgs[right]);}return ;}struct edgess t=edgs[left];struct edgess t1;int i=left;int j=right;while (i<j){while(edgs[j].weight>=t.weight&&j>i)j--;edgs[i]=edgs[j];while(edgs[i].weight<=t.weight&&i<j)i++;edgs[j]=edgs[i];}edgs[i]=t;quiksort(left,i-1);quiksort(i+1,right);}int getfather(int v){if (uni[v]==v)//递归实现寻找顶点的祖先{return v;}else{uni[v]=getfather(uni[v]);return uni[v];}}int merge(int u,int v)//并查集的实现{int n1,n2;n1=getfather(u);n2=getfather(v);if (n1!=n2){uni[n2]=n1;//实现相连的点有共同的祖先判断他们是否有共同的祖先就知道是否在同一集合return 1;}return 0;}int main(){cin>>point>>edge;for (int i=1;i<=edge;i++){cin>>po1>>po2>>w;edgs[i].p1=po1;edgs[i].p2=po2;edgs[i].weight=w;}quiksort(1,edge);for (i=1;i<=edge;i++){cout<<edgs[i].weight<<endl;}for (i=1;i<=point;i++){uni[i]=i;}//核心思想for (i=1;i<=edge;i++){if (merge(edgs[i].p1,edgs[i].p2))//根据排序后的权值来选择边的顶点来计算最小生成树{count++;sum=sum+edgs[i].weight;}if (count==point-1)//如果计数满足了边数立即结束{break;}}cout<<sum<<endl;return 0;}

0 0
原创粉丝点击