【java,Kruskal】实现最小生成树

【java,Kruskal】实现最小生成树。学习链接:学习链接

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Scanner;

class Edge{
	//边 a b c的含义是,a、b节点之间的路径权重(长度)是c
	int a;
	int b;
	int c;
	Edge(int a,int b,int c) {
		this.a = a;
		this.b = b;
		this.c = c;
	}
}

public class MST {
	private static int vertexNum;	//顶点的数量
	private static int edgeNum;		//边的数量
	private static Edge[] edgeArr;	//用来存储边
	private static int[] p;	//利用并查集
	private static int chooseEdgeNum = 0;//被选中的边的个数
	private static ArrayList<Integer> chooseEdge = new ArrayList<Integer>();	//记录被选中的边的下标
	
	public static void main(String args[]) {
		Scanner sc = new Scanner(System.in);
		vertexNum = sc.nextInt();
		edgeNum = sc.nextInt();
		edgeArr = new Edge[edgeNum];	//初始化存储边的数组
		p = new int[vertexNum+1];
		for (int i = 1; i <= vertexNum; i ++) {
            p[i] = i;//初始化并查集
        }
		//输入边
		int a,b,c;
		for(int i = 0 ; i < edgeNum ; i++) {
			sc.nextLine();
			a = sc.nextInt();
			b = sc.nextInt();
			c = sc.nextInt();
			edgeArr[i] = new Edge(a,b,c); 
		}
//		for(int i = 0 ; i < edgeNum ; i++) {
//			System.out.println(edgeArr[i].a+" "+edgeArr[i].b+" "+edgeArr[i].c);
//		}
		//Kruskal
		boolean temp = Kruskal();
		if(Kruskal() == true) {
			System.out.println("可以构成最小生成树,最小生成树包含的边有:");
			for(int i = 0; i<chooseEdge.size(); i++) {
				int m = chooseEdge.get(i);
				System.out.println("边: "+edgeArr[i].a+" --> "+edgeArr[i].b+" ,权重:"+edgeArr[i].c);
			}
		}
		else {
			System.out.println("不可以构成最小生成树");
		}
		
	}
	
	public static boolean Kruskal() {
		//对edge数组从小到大进行排序
		for(int i = 1 ; i < edgeNum ; i++) {
			Edge temp = edgeArr[i];	//定义待交换的元素
			int j;	//定义待插入的位置
			for(j = i ; j > 0 && temp.c < edgeArr[j-1].c ; j--) {
				edgeArr[j] = edgeArr[j-1];
			}
			edgeArr[j] = temp;
		}
		//逐个把边加入进去
		for(int i = 0 ; i < edgeNum ; i++) {
			Edge temp = edgeArr[i];
			int a = temp.a;
			int b = temp.b;
			int c = temp.c;
			//查看顶点a 顶点b是否属于同一个集合
			int m = find(a);
			int n = find(b);
			if(m!=n) {
				//如果a、b两者不属于同一个集合,将a、b这条边加入到总集合中去
				p[m] = n;
				//System.out.println("加入:"+a+" "+b+" 祖先分别是"+m+" "+n);
				chooseEdgeNum++;
				chooseEdge.add(i);
			}
		}
		if (chooseEdgeNum < vertexNum - 1) {
	        // 边树小于n-1,不能构造最小生成树
	        return false;
	    } 
		else {
	        return true;
	    }

	}
	
	public static int find(int x) {
	    //寻找x点的祖宗节点
	    if (p[x] != x) {
	    	p[x] = find(p[x]);
	    }
	    return p[x];
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值