最小生成树-kruskal算法(非并查集的实现&优先队列的sh xian&并查集的实现)

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;
    }
}

猜你喜欢

转载自blog.csdn.net/anhuibozhoushatu/article/details/83787174