ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

最小生成树算法(Kruscal && Prim)

2019-03-23 17:50:35  阅读:283  来源: 互联网

标签:结点 Prim Scanner int util Kruscal && import new


在这里插入图片描述`

输入第一行连个数字n,m代表结点数和道路数
下面m行,每行输入三个数字t1,t2,t3,代表序号为t1的结点与序号为t2的结点之间的距离是t3
求最小生成树的长度miniTree

`

Kruscal

核心思想是基于贪心策略,每次从路径中选择路径权值最小的一条边,并且每次都要判断这条边的两个结点的祖先是否都想同,如果不同(相同会出现环,故不能相同),则加入最小生成树集合中,直到加入的次数为n-1次,结束
解决方法

  1. 建立一个路径类,包含三个属性(结点1,结点2,两个结点之间的道路长度)
  2. 根据每次输入的t1,t2,t3,实例化相应的路径实例,每次创建一个,都要添加到list中
  3. 对list中的路径对象按照路径长度进行从小到大的排序
  4. 建立并查集函数,判断是否传入的两个结点序号是否来自一个祖先(防止环的出现)
  5. 建立Kruscal函数,建立一个变量用来更新每次新加入一条权值最短的路径后最小生成树长度的总和,迭代n-1次后,结束
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Scanner;

public class kruscal
{
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		int n = in.nextInt();//结点数
		int m = in.nextInt();//道路数
		List<Nodes> arr = new ArrayList<Nodes>();//存储路径对象
		int[] f = new int[n+1];//存储并查集
		//初始化并查集
		for(int i=1;i<=n;i++) {
			f[i] = i;//初始化为相应序号
		}
		//初始化arr数组
		for(int i=1;i<=m;i++) {
			int u = in.nextInt();
			int v = in.nextInt();
			int w = in.nextInt();
			arr.add(new Nodes(u,v,w));
		}
		System.out.println(Kruscal(arr, m, n,f));//输出最小生成树长度
	}
	

	static int Kruscal(List<Nodes> arr,int m,int n,int[] f){
		int miniSum = 0;//存储结果
		int times = 0;//计数器
		//根据w,对arr数组进行排序
		Collections.sort(arr, new Comparator<Nodes>() {
			public int compare(Nodes o1, Nodes o2) {
				return o1.w - o2.w;
			}});
		
		for(int i=0;i<m;i++)//有n个结点,表示生成树的边数最多为n-1
		{
			if(merge(arr.get(i).u, arr.get(i).v, f)) {//如果不是同一个祖先
				times++;
				miniSum+=arr.get(i).w;
			}
			if(times == n-1) {//最多需要找出n-1条路,达到这个次数,就立即退出
				break;
			}
		}
		return miniSum;
	}

	//递归寻找祖先结点
	static int getf(int x,int[] f){
		if(f[x]==x) {
			return x;
		}else {
			f[x] = getf(f[x],f);
			return f[x];
		}
	}


	//判断一条路的两个结点是否有同一个祖先,若有,该路径不能使用
	static boolean merge(int x1,int x2,int[] f){
		int t1 = getf(x1,f);
		int t2 = getf(x2,f);
		if(t1!=t2) {
			f[t2] = t1;//如果没有祖先,就让t1点作为t2点的祖先
			return true;
		}
		return false;
	}

}

class Nodes {
	int u;//结点1序号
	int v;//结点2序号
	int w;//结点1与结点2之间的权
	Nodes(int u,int v,int w){
		this.u = u;
		this.v = v;
		this.w = w;
	}
}

Prim

基于动态规划思想,每次选择能够连接最小生成树,并且距离最短的的一个结点加入最小生成树集合

package 图论;

import java.util.Scanner;

public class Prim {
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		System.out.println("输入城市数量和道路数");
		int n = in.nextInt();//城市数量
		int m = in.nextInt();//城市之间的道路数
		int[][] map = new int[n+1][n+1];
		int[] book = new int[n+1];
		for(int i=1;i<=n;i++) {
			for(int j=1;j<=n;j++) {
				map[i][j] = i==j?0:Integer.MAX_VALUE;
			}
		}
		System.out.println("输入城市之间的信息");
		for(int i = 1;i<=m;i++) {
			int t1 = in.nextInt();
			int t2 = in.nextInt();
			int dis = in.nextInt();
			map[t1][t2] = dis;
			map[t2][t1] = dis;
		}
		System.out.println("输入起点");
		int root = in.nextInt();
		System.out.println(prim(root, map, book));
	}
	
	static int prim(int root,int[][] map,int[] book) {
		int ans = 0;
		int len = book.length;
		int[] dis = new int[len];
		//创建资源数组
		for(int i = 1;i<len;i++) {
			dis[i] = map[root][i];
			//默认初始结点为结点1,初始化结点1到其他各个结点的距离
		}
		book[root] = 1;//标记root已经访问
		for(int k=1;k<len;k++) {
			int pos = 0;
			int min = Integer.MAX_VALUE;
			for(int i=1;i<len;i++) {
				//每次选择没有访问的,并且距离最小生成树距离最短的点
				if(book[i]==0 && dis[i]<min) {
					min = dis[i];
					pos = i;//标记序号
				}
			}
			//开始调整
			book[pos] = 1;
			ans+=dis[pos];//加入最小生成树
			for(int i = 1;i<len;i++) {
				if(book[i]==0 && dis[i]>map[pos][i]) {
					dis[i] = map[pos][i];
				}
			}
		}
		return ans;
	}
}

标签:结点,Prim,Scanner,int,util,Kruscal,&&,import,new
来源: https://blog.csdn.net/qq_37756310/article/details/88628497

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有