Java实现Kruskal,优化的前向量结构,并查集

28 篇文章 0 订阅

Kruskal思想:将所有边排序,每次选最小的边,检查这个边两个顶点是否为同一个集合,不是的话就合并,是的话就不要(会形成回路),最后选n-1个边。选边的过程可以由堆进行优化

package com.yxs.graph1;

import java.io.BufferedInputStream;
import java.util.PriorityQueue;
import java.util.Scanner;

public class Kruskal {
	static class Edge{
		int to, w, from;
		{
			to = w = from = 0;
		}
	}
	static final int MAXN = 105;
	static int[] head = new int[MAXN];
	static Edge[] edge = new Edge[MAXN];
	static int len = 1;
	static void add(int from, int to, int w) {
		edge[len] = new Edge();
		edge[len].from = from;
		edge[len].to = to;
		edge[len++].w = w;
	}
	
	static int[] parent = new int[MAXN];
	static int[] tnums = new int[MAXN];
	static {
		for(int i = 0; i < parent.length;i++) {
			parent[i] = i;
			tnums[i] = 1;
		}
	}
	
	static int getParent(int x) {
		if(x == parent[x])return x;
		else return parent[x] = getParent(parent[x]);
	}
	
	static boolean isSameset(int x, int y) {
		int px = getParent(x);
		int py = getParent(y);
		if(px == py)return true;
		return false;
	}
	
	static void union(int x, int y) {
		int px = getParent(x);
		int py = getParent(y);
		if(px != py) {
			if(tnums[px] <= tnums[py]) {
				parent[px] = py;
				tnums[py] += tnums[px];
			}else {
				parent[py] = px;
				tnums[px] += tnums[py];
			}
		}
	}
	
	static void kruskal(int n) {//基于堆优化
		PriorityQueue<Edge> queue = new PriorityQueue<>(
			(x, y)->{
				return x.w - y.w;
			});
		for(int i = 1;i < len;i++) {
			queue.add(edge[i]);
		}
		int ans = 0, cnt = 0;
		while(!queue.isEmpty() && cnt != n-1) {
			Edge e = queue.poll();
			if(!isSameset(e.from,e.to)) {
				ans+=e.w;
				cnt++;
				union(e.from,e.to);
			}
		}
		System.out.println("最小生成树的权值为:" + ans);
	}
	
	public static void main(String[] args) {
		Scanner in = new Scanner(new BufferedInputStream(System.in));
		int n = in.nextInt();
		int e = in.nextInt();
		for(int i = 1;i <= e;i++) {
			int from = in.nextInt();
			int to = in.nextInt();
			int w = in.nextInt();
			add(from, to, w);
		}
		kruskal(n);
	}
}
/*
6 8
1 6 100
1 5 30
1 3 10
2 3 5
3 4 50
4 6 10
5 4 20
5 6 60
*/ 

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值