#include <iostream>
#define INF 0x3fff
#define MAXN 100
using namespace std;
typedef struct
{
int s;//start结点
int e;//end结点
int w;//weight权值
}edge;
edge e[MAXN*MAXN/2];//存储每一条边的数组
void insertsort(edge e[],int n)//直接插入排序
{
int i,j;
edge temp;
for(i = 0 ; i < n ;i++)
{
temp = e[i];
j = i - 1;
while(j >= 0 && temp.w < e[j].w)
{
e[j+1]= e[j];
j--;
}
e[j+1] = temp;
}
}
void kruskal(int n,int mat[][MAXN])//Kruskal实现
{
int i,j,k,m1,m2,sn1,sn2;
edge e[MAXN*MAXN/2];
int vset[MAXN];
for(i = 0 ; i < n ; i++)//每个节点都初始化
vset[i] = i;
k = 0;
for(i = 0 ; i < n;i++)
{
for(j = 0 ; j < n;j++)
{
if(mat[i][j] != 0 && mat[i][j] != INF)//将邻接矩阵中的每一条边都加入到边权值的数组中
{
e[k].s = i;e[k].e = j;
e[k].w = mat[i][j];
k++;
}
}
}
insertsort(e,k);//对边的权值从大到小排序,这里采用直接插入排序,如果采用堆排序时间复杂度会减少
int cnt = 1 ;//记录加入到最小生成树的边的数量
k = 0;
while(cnt < n)
{
m1 = e[k].s; m2 = e[k].e;//记录这条边的start , end 结点
sn1 = vset[m1]; sn2 = vset[m2];//看这两个结点属于哪一个set
if(sn1 != sn2)//如果不等,说明这两个结点不在一个生成树中,合并
{
printf("edge (%d,%d):%d is added!\n", e[k].s,e[k].e,e[k].w);
cnt++;
for(i = 0 ; i < n ; i++)
{
if(vset[i] == sn2)//把所有的原有的生成树的结点重新加入到新的生成树中
vset[i] = sn1;
}
}
k++;//k为边的权值数组的Index
}
}
int mat[MAXN][MAXN];
int main()
{
memset(mat,0,sizeof(mat));
int num;
printf("please input vertex:");
scanf("%d",&num);
int n;
printf("input the number of edge:");
scanf("%d",&n);
int t = n;
while(t--)
{
int a,b,cost;
scanf("%d %d %d",&a,&b,&cost);
--a,--b;
if(mat[a][b] == 0 && mat[b][a] == 0 || cost < mat[a][b] )
mat[a][b] = mat[b][a] = cost;
}
int i,j;
for(i = 0 ; i < num;i++){
for(j = 0 ; j < num; j++)
printf("%4d",mat[i][j]);printf("\n");}
kruskal(num,mat);
/*
test data:
6
10
1 2 6
1 3 1
1 4 5
2 3 5
3 4 5
2 5 3
3 5 6
3 6 4
4 6 2
5 6 6
*/
return 0;
}