kruskal算法:构造一个只含n个顶点,而边集为空的子图,若将该子图中各个顶点看成是各棵树的根节点,则它是一个含有n棵树的森林 。之后,从网的边集中选取一条权值最小的边,若该边的两个顶点分属不同的树 ,则将其加入子图,也就是这两个顶点分别所在的 两棵树合成一棵树;反之,若该边的两个顶点已落在同一棵树上,则不可取,而应该取下一条权值最小的边再试之。依次类推,直至森林只有一棵树。kruskal算法能够在并查集的基础很快的实现。结合例子来介绍具体算法实现(其中并查集的部分可以详见并查集介绍部分) http://poj.org/problem?id=1251
非并查集的实现
import java.util.*;
public class kruskal {
public static void main(String args[]){
Scanner in=new Scanner(System.in);
while(in.hasNext()){
int V=in.nextInt();
int E=in.nextInt();
List<Eg> eg=new ArrayList<Eg>();//用于存储边
for(int i=0;i<E;i++){
int x=in.nextInt();
int y=in.nextInt();
int value=in.nextInt();
//去除重复边
int flag1=1;
for(int j=0;j<eg.size();j++){
if(eg.get(j).x==x &&eg.get(j).y==y){
if(value<eg.get(j).value){
eg.get(j).setValue(value);
}
flag1=0;
break;
}
}
if(flag1==1){
eg.add(new Eg(x,y,value));
}
}
//MST算法
List<Eg> ans=new ArrayList<Eg>();
int visit[]=new int[V+1];
for(int i=0;i<V-1;i++){
int posi=-1;
int posj=-1;
int mineg=Integer.MAX_VALUE;
for(int j=0;j<eg.size();j++){
Eg temp1=eg.get(j);
if(visit[temp1.x]==0 || visit[temp1.y]==0){
if(temp1.value<mineg){
posi=temp1.x;
posj=temp1.y;
mineg=temp1.value;
}
}
}
visit[posi]=1;
visit[posj]=1;
ans.add(new Eg(posi,posj,mineg));
}
//打印结果
for(int i=0;i<ans.size();i++){
Eg temp2=ans.get(i);
System.out.println(temp2.x+" "+temp2.y+" "+temp2.value);
}
}
}
}
//定义好边的数据结构
class Eg{
int x;
int y;
int value;
Eg(int x,int y,int value){
this.x=x;
this.y=y;
this.value=value;
}
public void setValue(int value){
this.value=value;
}
优先队列的实现:
import java.util.*;
public class kruskal_queue {
public static void main(String args[]){
Scanner in=new Scanner(System.in);
while(in.hasNext()){
int V=in.nextInt();
int M=in.nextInt();
Map<String,Integer> map=new HashMap<String,Integer>(); //map用于查询比较快
Queue<E> queue=new PriorityQueue<E>(new Comparator<E>() {
@Override
public int compare(E o1, E o2) {
return o1.value-o2.value;
}
});
for(int i=0;i<M;i++){
int x=in.nextInt();
int y=in.nextInt();
//考虑无向图,统一将小顶点放在前面,大顶点放在后面
int xx=x;
int yy=y;
x=Math.min(xx,yy);
y=Math.max(xx,yy);
int value=in.nextInt();
if(map.containsKey(x+" "+y)){
if(map.get(x+" "+y)>value){
map.remove(x+" "+y);
map.put(x+" "+y,value);
}
}else{
map.put(x+" "+y,value);
}
}
for(String key:map.keySet()){
String str[]=key.split(" ");
queue.offer(new E(Integer.valueOf(str[0]),Integer.valueOf(str[1]),map.get(key)));
}
int visit[]=new int[V+1];
List<E> ans=new ArrayList<E>();
int cnt=0;
while(queue.size()>0){
E temp4=queue.poll();
if(visit[temp4.x]==0 || visit[temp4.x]==0){
ans.add(temp4);
cnt++;
if(cnt==V-1)
break;
}
}
for(int i=0;i<ans.size();i++){
E temp5=ans.get(i);
System.out.println(temp5.x+" "+temp5.y+" "+temp5.value);
}
}
}
}
//使用优先队列实现卡路斯卡尔算法
class E{
int x;
int y;
int value;
E(int x,int y,int value){
this.x=x;
this.y=y;
this.value=value;
}
public void setValue(int value){
this.value=value;
}
}