/******************Kruskal算法 < 求最小生成树 > 时间复杂度为eloge{e为图中的边的数目}    
Kruskal思想:对G<V,E>来说,初始时的最小树集合T<V,0>无边,只有|V|个顶点;
不断地从集合E中选出在T中不构成回路,且边权最小的边;
直到集合T中边的数目为|V|-1;或者 T的连通分支为1 。
Kruskal算法实现步骤:
1.根据邻接矩阵初始化边<结构体数组>的信息,置连通分支个数为|V|;
2.当前连通分支个数为1时,结束。否则,从<E-T-U>中选择边权最小的边e;{U是当前会构成回路的边的集合}
3.判断新加入的边是否构成回路,若是,修改U集合,转2 ;否则,加入T中。    
******************/
#include<iostream>
#define N 6
#define NUM 100
#define MAX 1000
using namespace std;
int edge[N][N]={{MAX,6,1,5,MAX,MAX},
                                {6,MAX,5,MAX,3,MAX},
                                {1,5,MAX,5,6,4},
                                {5,MAX,5,MAX,MAX,2},
                                {MAX,3,6,MAX,MAX,6},
                                {MAX,MAX,4,2,6,MAX}};
struct EDGE{
    int v1;//边起点    
    int v2;//边终点    
    int val;//边权    
}e[NUM];

int edge_num=0; //存储边数
int con[N];//存储图的连通情况    
int cnt=N; //存储图的连通度    
int status[NUM]={0};//边的状态<-1表示此边加入会构成回路,被舍弃;0表示此边暂未被处理;1表示此边已在最小树中>                                                                                                            
bool Union(int a, int b)
{
         int i;
         int beg_degree=con[a];
         int end_degree=con[b];    
         if(con[a]!=con[b]){
                --cnt;//此时连通度减一    
                for(i=0; i<N; ++i)
                     if(con[i]==beg_degree ||con[i]==end_degree){
                         con[i]=cnt;
                     }
                return true;
         }    
         else return false;
}
void Kruskal()
{
         int i, j;
         int min, num=0;    
         int temp_v1, temp_v2, temp;
            // temp_v1存储边的起点
            //temp_v2存储边的终点
            //temp存储边的序号
         //初始化连通度 ,此时一个顶点就是一个连通分支    
         for(i=0; i<N; ++i)
         con[i]=N+i;    
         while(num<N-1){//最小树的边的数目num小于{顶点数-1}时就一直执行    
            min=MAX;    
            for(j=0; j<edge_num; ++j)
             if(min>e[j].val && status[j]==0){
                    temp_v1=e[j].v1;
                    temp_v2=e[j].v2;
                    min=e[j].val;
                    temp=j;
             }
             if(Union(temp_v1, temp_v2)){
                status[temp]=1;
                ++num;
             }
             else{
                status[temp]=-1;
             }
         }
}
int main()
{
        int i, j;
        for(i=0; i<N; ++i)
        for(j=0; j<N; ++j)
            if(edge[i][j]!=MAX){
             e[edge_num].v1=i;
             e[edge_num].v2=j;
             e[edge_num].val=edge[i][j];
             ++edge_num;
            }
        Kruskal();
        cout<<"最小生成树:"<<endl;
        cout<<"起点|终点|边权"<<endl;    
        for(i=0; i<edge_num; ++i){
         if(status[i]==1){
            cout<<e[i].v1+1<<"        "<<e[i].v2+1<<"        "<<e[i].val<<endl;
         }
        }
        system("pause");
        return 0;
}