Kruskal和Prim算法求最小生成树
Kruskal算法求最小生成树
测试数据:
5 6
0 1 5
0 2 3
1 2 4
2 4 2
2 3 1
1 4 1
输出:
2 3 1
1 4 1
2 4 2
0 2 3
思路:在保证不产生回路的情况下,选择权值小的边。是否产生回路采用并查集来实现
判断两个点是否连通:如果两个点的祖先不是同一个,说明这两个点不可联通,要标志两个点联通,只要使两个点的祖先是同一个。关于并查集的讲解可以看我转载的一篇文章。
比如初始化的时候ABC的祖先是他自己,先加入了AB这条边,这两个点的的父亲不一样,可以加入这条边,同时将A的祖先设置为B的祖先。同样AC加入也是这样,将C的父亲设为A的祖先B。这时候发现ABC相互可达,他们的祖先都是一个B。这个时候如果要添加BC这条边,查看BC的祖先,发现祖先一样,说明这两个点是可达的,那么如果添加这条边就会产生回路。
总的来说,将相邻的边所有顶点的祖先设置为同一个,如果两个顶点的祖先是同一个,那么就表明这两个点是可达的。那么如果还要添加这个以这两个顶点为顶点的边,就会产生回路。
import java.io.BufferedReader;
import java.io.FileReader;
public class Kruskal {
static int father[];
static Edge edges[];
static Edge tree[];
static int verNum,edgeNum;
public static void main(String[] args) throws Exception {
readData();
initFather();
getTree();
}
/**
* 读取文本的数据
* @throws Exception
*/
private static void readData()throws Exception {
// TODO 自动生成的方法存根
BufferedReader bf=new BufferedReader(new FileReader("d:/testGraphic.txt"));
String strings[]=bf.readLine().split(" ");
verNum=Integer.parseInt(strings[0]);
edgeNum=Integer.parseInt(strings[1]);
edges=new Edge[edgeNum];
tree=new Edge[verNum-1];
for (int i = 0; i < edgeNum; i++) {
strings=bf.readLine().split(" ");
edges[i]=new Edge(Integer.parseInt(strings[0]),Integer.parseInt(strings[1]),Integer.parseInt(strings[2]));
}
sort();
bf.close();
}
/**
* 将各条边按照权值从小到大进行排列
*/
public static void sort()
{
for (int i = 0; i < edges.length; i++) {
for (int j = i+1; j < edges.length; j++) {
if(edges[j].weight<edges[i].weight)
{
Edge temp=edges[j];
edges[j]=edges[i];
edges[i]=temp;
}
}
}
}
/**
* 初始化每个点的父亲设置为自己
*/
private static void initFather() {
// TODO 自动生成的方法存根
father=new int[verNum];
for (int i = 0; i < father.length; i++) {
father[i]=i;
}
}
/**
* 获得最小生成树
*/
private static void getTree() {
// TODO 自动生成的方法存根
int edgesIndex=0;
int treeIndex=0;
while(true)
{
//如果边数够了跳出循环
if(treeIndex==verNum-1)
break;
int father1=findFather(edges[edgesIndex].from);
int father2=findFather(edges[edgesIndex].end);
//如果两个的点的父亲不相同 则说明不连通
if(father1!=father2)
{
tree[treeIndex++]=edges[edgesIndex];
father[father1]=father2;
}
edgesIndex++;
}
//输出树
printTree();
}
private static void printTree() {
// TODO 自动生成的方法存根
for (int i = 0; i < tree.length; i++) {
Edge edge=tree[i];
System.out.println(edge);
}
}
/**
* 查找一个点的父亲
* @param i
* @return
*/
public static int findFather(int i)
{
//如果一个点的父亲是自己 返回
if(father[i]==i)
return i;
//否则一直查找他的顶层。
else
{
int f=i;
while(father[f]!=f)
{
f=father[f];
}
father[i]=father[f];
return father[f];
}
}
}
class Edge
{
public int from;
public int end;
public int weight;
public Edge(int from,int end,int weight)
{
this.from=from;
this.end=end;
this.weight=weight;
}
public String toString()
{
return this.from+" "+this.end+" "+this.weight;
}
}
prim算法求最小生成树
思路:先随机找一个点添加到点集U中,在V-U中找一个点与U点集中关联并且权值最小的点,然后将这个点添加到点集U中,依次下去,直至U==V
测试数据:
5 6
0 2 3
1 2 4
2 4 2
2 3 1
1 4 1
输出:
0 2 3
2 3 1
2 4 2
4 1 1
import java.io.BufferedReader;
import java.io.FileReader;
public class Prime {
static int array[][];
static int verNum,edgeNum;
/**
* 读取文本数据
* @throws Exception
*/
public static void readData() throws Exception
{
BufferedReader bf=new BufferedReader(new FileReader("d:/testGraphic.txt"));
String strings[]=bf.readLine().split(" ");
verNum=Integer.parseInt(strings[0]);
edgeNum=Integer.parseInt(strings[1]);
array=new int [verNum][verNum];
//用矩阵表示两个点之间的权值,如果是相同点标志为0 如果两个点不关联设为100
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array.length; j++) {
if(i==j)
array[i][j]=0;
else
array[i][j]=100;
}
}
//根据文本进行赋值
for (int i = 0; i < edgeNum; i++) {
strings=bf.readLine().split(" ");
int a=Integer.parseInt(strings[0]);
int b=Integer.parseInt(strings[1]);
int c=Integer.parseInt(strings[2]);
array[a][b]=c;
array[b][a]=c;
}
}
/**
* 打印生成最小树
* @param tree
*/
public static void printTree(int tree[][])
{
for(int a[]:tree)
{
for(int b:a)
{
System.out.print(b+" ");
}
System.out.println();
}
}
public static void main(String[] args) throws Exception
{
readData();
//创建最小生成树
int tree[][]=new int [verNum-1][3];
//取一个点放到点集U
int k=0;
CloseEdge edge[]=new CloseEdge[verNum];
//其他点和点K的权值
for (int i = 0; i < verNum; i++) {
edge[i]=new CloseEdge(k,array[k][i]);
}
edge[k]=new CloseEdge(k,0);
//执行次数为边的数量
for (int o = 0; o< verNum-1; o++)
{
int min=Integer.MAX_VALUE;
//在V-U中的点中找一个和U中点关联的并且权值最小的加入到U
for (int i = 0; i <verNum; i++) {
if(edge[i].weight!=0&&edge[i].weight<min)
{
min=edge[i].weight;
k=i;
}
}
//将新选取点的权值存到数中
tree[o][2]=edge[k].weight;
//设置选中的点到U的权值为0,表示已经在U中
edge[k].weight=0;
//将新增加的变记录下来,第0个点是与新顶点相关联的的点,第一个顶点是新的顶点
tree[o][0]=edge[k].index;
tree[o][1]=k;
//因为有新顶点加入,所以重新设置V-U与点集U中点关联的最小的权值
for (int i = 0; i < edge.length; i++) {
if(array[k][i]<edge[i].weight)
edge[i]=new CloseEdge(k,array[k][i]);
}
}
printTree(tree);
}
}
class CloseEdge
{
int index;
int weight;
/**
*
* @param index
* @param weight
*/
public CloseEdge(int index,int weight)
{
this.index=index;
this.weight=weight;
}
}
Kruskal和Prim算法求最小生成树的更多相关文章
- HDU-1233 还是畅通工程 (prim 算法求最小生成树)
prim 算法求最小生成树 还是畅通工程 Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Oth ...
- 858. Prim算法求最小生成树(模板)
给定一个n个点m条边的无向图,图中可能存在重边和自环,边权可能为负数. 求最小生成树的树边权重之和,如果最小生成树不存在则输出impossible. 给定一张边带权的无向图G=(V, E),其中V表示 ...
- Prim算法求最小生成树
首先在介绍这个算法之前我们要之明确一下什么是最小生成树的概念: 由 V 中的全部 n 个顶点和 E 中 n−1 条边构成的无向连通子图被称为 G 的一棵生成树,其中边的权值之和最小的生成树被称为无向图 ...
- 图的普里姆(Prim)算法求最小生成树
关于图的最小生成树算法------普里姆算法 首先我们先初始化一张图: 设置两个数据结构来分别代表我们需要存储的数据: lowcost[i]:表示以i为终点的边的最小权值,当lowcost[i]=0说 ...
- AcWing 858. Prim算法求最小生成树 稀疏图
//稀疏图 #include <cstring> #include <iostream> #include <algorithm> using namespace ...
- 最小生成树——Kruskal与Prim算法
最小生成树——Kruskal与Prim算法 序: 首先: 啥是最小生成树??? 咳咳... 如图: 在一个有n个点的无向连通图中,选取n-1条边使得这个图变成一棵树.这就叫“生成树”.(如下图) 每个 ...
- 利用Kruskal算法求最小生成树解决聪明的猴子问题 -- 数据结构
题目:聪明的猴子 链接:https://ac.nowcoder.com/acm/problem/19964 在一个热带雨林中生存着一群猴子,它们以树上的果子为生.昨天下了一场大雨,现在雨过天晴,但整个 ...
- 图的建立(邻接矩阵)+深度优先遍历+广度优先遍历+Prim算法构造最小生成树(Java语言描述)
主要参考资料:数据结构(C语言版)严蔚敏 ,http://blog.chinaunix.net/uid-25324849-id-2182922.html 代码测试通过. package 图的建 ...
- Prim算法和Kruskal算法求最小生成树
Prim算法 连通分量是指图的一个子图,子图中任意两个顶点之间都是可达的.最小生成树是连通图的一个连通分量,且所有边的权值和最小. 最小生成树中,一个顶点最多与两个顶点邻接:若连通图有n个顶点,则最小 ...
随机推荐
- Objective-C日记-之编码对象属性
NSCoder类 1,概述 将对象的实例变量和其他数据编码为数据块,然后将他们存在到磁盘当中:以后将这些数据块读回到内存中,并且还基于保存的数据创建新的对象,也称序列化或反序列化. 2,用法 a,首先 ...
- 3299: [USACO2011 Open]Corn Maze玉米迷宫
3299: [USACO2011 Open]Corn Maze玉米迷宫 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 137 Solved: 59[ ...
- Tyvj P1813 [JSOI2008]海战训练
P1813 [JSOI2008]海战训练 时间: 1000ms / 空间: 131072KiB / Java类名: Main 描述 为了准备高层峰会,元首命令武装部队必须处于高度戒备.警察将监视每一条 ...
- Javascript基础知识小测试(一)
这里罗列了<你不知道的js>上卷的一些知识点以及小问题,如果你想巩固一下js那么就和我一起来看看吧. 如果你能不看书就回答上80%的问题说明你js的这一部分学得还不错,再接再厉. 作用域和 ...
- 【转】Django HTTP请求的处理流程
Django 和其他 Web 框架的 HTTP 处理的流程大致相同,Django 处理一个 Request 的过程是首先通过中间件,然后再通过默认的 URL 方式进行的.我们可以在 Middlewar ...
- CentOS 安装mysql-5.7.10(glibc版)
注:所有shell命令都以root用户执行. 一.下载 shell> cd /home/user/Downloads shell> wget http://mirrors.sohu.com ...
- springmvc基础学习2---简单配置文件
1:web文件 2:spring-mvc.xml配置文件
- JAVA基础知识(2)--关键字final的使用
/***Final关键字的使用*@author lihaiming*Email:912547587@qq.com*关键字Final可以修饰属性,方法,类*修饰属性的时候,final修饰的变量是一个常量 ...
- TextView字体大小及颜色设置
TextView设置文字大小及颜色: 1.1)通过xml配置 <TextView android:layout_width="match_parent" a ...
- 实用 .htaccess 用法大全
这里收集的是各种实用的 .htaccess 代码片段,你能想到的用法几乎全在这里. 免责声明: 虽然将这些代码片段直接拷贝到你的 .htaccess 文件里,绝大多数情况下都是好用的,但也有极个别情况 ...