最小生成树性质:设G=(V,E)是一个连通网络,U是顶点集V的一个真子集。若(u,v)是G中一条“一个端点在U中(例如:u∈U),另一个端点不在U中的边(例如:v∈V-U),且(u,v)具有最小权值,则一定存在G的一棵最小生成树包括此边(u,v)。
该定理阐明的属性也被称之为切割属性,简单讲就是横跨该切割的权重最小的边,即一端在s,另一端v-s,这条边一定在某一颗最小生成树的一条边上
克鲁斯卡尔算法步骤:
1.对所有边的权值进行递增排序,
2.对于从小到大的每一条边,如果加入后不构成环就加入,反之排除在外,直到所有边判断完毕。【ps:算法时间取决于边的数目】
下面是伪代码
可以看到,2步操作执行的正是并查集的find union操作
算法的正确性证明:使用数学归纳法,针对顶点
1.n=2时,即只有两个点的时候,该算法显然成立,一次得结果
2.n>2时,假设2<=j<n,成立,即n-1顶点已经连通了,这是一颗n-1个顶点的最小生成树,后面选择权值最小的一条能联通n个顶点的边加入即构成最小生成树
假设这个边不在最小生成树上,那么存在一条边小于这个权值的一条边,显然它应该在之前被选出来,那样的话把它加入到这n-1个顶点中就构成了环,删除一条权值最大的边,就产生了一颗权值更小的n-1个顶点的最小生成树,这与条件相左,说明该方法是正确的
package org.kruskal;
import java.util.Scanner;
class Edge
{
public int begin;
public int end;
public int weight;
}
class Graph
{
public int vertexnum;
public int edgenum;
public Edge []edges;
public int []parent;
}
public class Kruskal {
public int find (int i,int []array)
{
while(array[i]!=i)
{
i=array[i];
}
return i;
}
public void union(int i,int j,int []array)
{
array[i]=j;
}
public void KruskalInit(Graph g)
{
Scanner input=new Scanner(System.in);
System.out.println("input vertexnum and edgenum");
g.vertexnum=input.nextInt();
g.edgenum=input.nextInt();
int parent[]=new int[g.vertexnum+1];
Edge edges[]=new Edge[g.edgenum];
for(int i=0;i<edges.length;i++)
{
edges[i]=new Edge();
System.out.println("input begin,end,weight");
edges[i].begin=input.nextInt();
edges[i].end=input.nextInt();
edges[i].weight=input.nextInt();
}
for(int i=1;i<parent.length;i++)
{
parent[i]=i;
}
g.edges=edges;
g.parent=parent;
}
public void KruskalSort(Graph g)
{
int edgenum=g.edgenum;
for(int i=0;i<edgenum-1;i++)
{
for(int j=0;j<edgenum-i-1;j++)
{
if(g.edges[j].weight>g.edges[j+1].weight)
{
Edge edge=g.edges[j];
g.edges[j]=g.edges[j+1];
g.edges[j+1]=edge;
}
}
}
}
public void KruskalCount(Graph g)
{
this.KruskalInit(g);
KruskalSort(g);
int vertexnum=g.vertexnum-1;
int sum=0;
for(int i=0;i<g.edgenum&&vertexnum!=0;i++)
{
int n=find(g.edges[i].begin,g.parent);
int m=find(g.edges[i].end,g.parent);
if(n!=m)
{
union(n,m,g.parent);
sum+=g.edges[i].weight;
vertexnum--;
}
}
if(vertexnum==0)
{
System.out.println("this is MiniSpanTree Weight is "+sum);
}
else
{
System.out.println("error");
}
}
public static void main(String args[])
{
Kruskal k=new Kruskal();
Graph g=new Graph();
k.KruskalCount(g);
}
}