/*用克鲁斯尔算法求最小生成树*/
#include <iostream>
using namespace std;
/*邻接矩阵的类型定义*/
#define MAX 10000000
#define MAX_VERTEX_NUM 20
typedef struct
{
char vexs[MAX_VERTEX_NUM];//用一维数组存储顶点信息
int edges[MAX_VERTEX_NUM][MAX_VERTEX_NUM];//用二维数组充当矩阵,来存储顶点边的信息
int vexnum,edgenum;//顶点树和边数
}MGraph;
/*构造无向联通网的邻接矩阵*/
void CreateUDN_AM(MGraph &G,int n,int e)
{
G.vexnum=n;
G.edgenum=e;
int i,j,k;
for(i=0;i<n;i++)
cin>>G.vexs[i];//输入顶点信息
for(i=0;i<n;i++)
for(j=0;j<n;j++)
G.edges[i][j]=MAX;//将矩阵初始化为无穷大
for(k=0;k<e;k++)
{
cin>>i>>j;
cin>>G.edges[i][j];//这里只用输入对称的边就行,也就是输入下矩阵或是上矩阵
G.edges[j][i]=G.edges[i][j];
}
}
//边表结点类型的定义
typedef struct
{
int begin,end;//边的起点和终点
int cost;//边上的权值
}EDGE;
EDGE edge[MAX_VERTEX_NUM];
//冒泡排序
void bubble_sort(EDGE edge[],int n)
{
int i,j;
int t;
for(i=0;i<n;i++)
for(j=i+1;j<n;j++)
if(edge[i].cost>edge[j].cost)
{
t=edge[i].cost;
edge[i].cost=edge[j].cost;
edge[j].cost=t;
t=edge[i].begin;
edge[i].begin=edge[j].begin;
edge[j].begin=t;
t=edge[i].end;
edge[i].end=edge[j].end;
edge[j].end=t;//将位置及权值都进行交换
}
}
//找f这个元素所在的连通分量中的标记元素的位置
int find(int forest[],int f)
{
while(forest[f]>0)
f=forest[f];
return f;
}
//求最小生成树
void MiniSpanTree_Kruskal(MGraph &G)
{
int i,j,k=0;
int LocationOfBegin,LocationOfEnd;
int forest[MAX_VERTEX_NUM];
for(i=0;i<G.vexnum;i++)
for(j=i+1;j<G.vexnum;j++)
if(G.edges[i][j]<MAX)
{
edge[k].begin=i;
edge[k].end=j;
edge[k].cost=G.edges[i][j];
k++;
}//将边及边的信息赋值到edge数组中
bubble_sort(edge,G.edgenum);//对edge里的元素按权值进行由小到大进行排序
for(i=0;i<G.edgenum;i++)
forest[i]=0;//初始化每个顶点,将每个顶点看做一个连通分量,并且置标识为0
for(i=0;i<G.edgenum;i++)
{
LocationOfBegin=find(forest,edge[i].begin);
LocationOfEnd=find(forest,edge[i].end);//找该顶点所在连通分量的标记元素的位置
if(LocationOfBegin!=LocationOfEnd)
{//如果起点和终点所在的连通分量的标记元素的地址相同,说明起点和终点在同一个连通分量中
forest[LocationOfBegin]=LocationOfEnd;//该句的作用是将两个连通分量连成一个连通分量
cout<<edge[i].begin<<"-"<<edge[i].end<<":"<<edge[i].cost<<endl;
}
}
}
void main()
{
freopen("a.txt","r",stdin);
MGraph G;
CreateUDN_AM(G,6,9);
MiniSpanTree_Kruskal(G);
}