赞
踩
生成树:包含全部顶点的一个极小连通子图
最小生成树:代价(权值和)最小的生成树
算法:Kruskal算法
输入:无向连通网G=(V,E)
输出:最小生成树T=(U,TE)
1. 初始化:U=V;TE={ }
2. 重复下述操作直到所有顶点位于一个连通分量中
3.在E中选取最短边(u,v),
图的存储结构:边集数组
合并连通分量:并查集
并查集:集合中的元素组织成树的形式:
(1)查找两个元素是否属于同一集合:所在树的根结点是否相同
(2)合并两个集合:将一个集合的根结点作为另一个集合根结点的孩子
- #include <iostream>
-
- using namespace std;
- struct EdgeType{//边集数组
- int from,to,weight;//起点,终点,权值
- };
- class EdgeGraph{
- public:
- EdgeGraph(char a[],int n,int e);
- ~EdgeGraph();
- void Kruskal();
- int FindRoot(int parent[],int v);//求顶点v所在集合的根
- private:
- char vertex[10];
- EdgeType edge[100];
- int vertexNum,edgeNum;
- };
-
- EdgeGraph::EdgeGraph(char a[],int n,int e){
- int i,j,k,w;
- vertexNum=n;edgeNum=e;
- for(i=0;i<vertexNum;i++)
- vertex[i]=a[i];
- for(k=0;k<edgeNum;k++){
- cout<<"请输入边的两个顶点编号和边的权值:";
- cin>>i>>j>>w;
- edge[k].from=i;edge[k].to=j;edge[k].weight=w;
- }
- }
- EdgeGraph::~EdgeGraph(){}
-
- void EdgeGraph::Kruskal(){
- int num=0,i,vex1,vex2;
- int parent[vertexNum];//双亲表示法存储并查集
- for(i=0;i<vertexNum;i++)
- parent[i]=-1;//初始化没有双亲,置-1
- for(num=0,i=0;num<vertexNum-1;i++){//在已排好序的边集数组中找最短边
- vex1=FindRoot(parent,edge[i].from);
- vex2=FindRoot(parent,edge[i].to);
- if(vex1!=vex2){//分属两个集合
- cout<<"("<<edge[i].from<<","<<edge[i].to<<")"<<" "<<edge[i].weight<<endl;
- parent[vex2]=vex1;//合并集合
- num++;
- }
- }
- }
-
- EdgeGraph::FindRoot(int parent[],int v){
- int t=v;
- while(parent[t]>-1)
- t=parent[t];//求顶点t的双亲一直到根
- return t;
- }
-
- //(1 4 12)(2 3 17)(0 5 19) (2 5 25)(3 5 25)(4 5 26)(0 1 34)(3 4 38)(0 2 46)
- int main()
- {
- char ch[6]={'A','B','C','D','E','F'};
- EdgeGraph eg(ch,6,9);
- eg.Kruskal();
- return 0;
- }
- 运行结果
- 请输入边的两个顶点编号和边的权值:1 4 12
- 请输入边的两个顶点编号和边的权值:2 3 17
- 请输入边的两个顶点编号和边的权值:0 5 19
- 请输入边的两个顶点编号和边的权值:2 5 25
- 请输入边的两个顶点编号和边的权值:3 5 25
- 请输入边的两个顶点编号和边的权值:4 5 26
- 请输入边的两个顶点编号和边的权值:0 1 34
- 请输入边的两个顶点编号和边的权值:3 4 38
- 请输入边的两个顶点编号和边的权值:0 2 46
- (1,4) 12
- (2,3) 17
- (0,5) 19
- (2,5) 25
- (4,5) 26
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。