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算法求最小生成树的更多相关文章

  1. HDU-1233 还是畅通工程 (prim 算法求最小生成树)

    prim 算法求最小生成树 还是畅通工程 Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Oth ...

  2. 858. Prim算法求最小生成树(模板)

    给定一个n个点m条边的无向图,图中可能存在重边和自环,边权可能为负数. 求最小生成树的树边权重之和,如果最小生成树不存在则输出impossible. 给定一张边带权的无向图G=(V, E),其中V表示 ...

  3. Prim算法求最小生成树

    首先在介绍这个算法之前我们要之明确一下什么是最小生成树的概念: 由 V 中的全部 n 个顶点和 E 中 n−1 条边构成的无向连通子图被称为 G 的一棵生成树,其中边的权值之和最小的生成树被称为无向图 ...

  4. 图的普里姆(Prim)算法求最小生成树

    关于图的最小生成树算法------普里姆算法 首先我们先初始化一张图: 设置两个数据结构来分别代表我们需要存储的数据: lowcost[i]:表示以i为终点的边的最小权值,当lowcost[i]=0说 ...

  5. AcWing 858. Prim算法求最小生成树 稀疏图

    //稀疏图 #include <cstring> #include <iostream> #include <algorithm> using namespace ...

  6. 最小生成树——Kruskal与Prim算法

    最小生成树——Kruskal与Prim算法 序: 首先: 啥是最小生成树??? 咳咳... 如图: 在一个有n个点的无向连通图中,选取n-1条边使得这个图变成一棵树.这就叫“生成树”.(如下图) 每个 ...

  7. 利用Kruskal算法求最小生成树解决聪明的猴子问题 -- 数据结构

    题目:聪明的猴子 链接:https://ac.nowcoder.com/acm/problem/19964 在一个热带雨林中生存着一群猴子,它们以树上的果子为生.昨天下了一场大雨,现在雨过天晴,但整个 ...

  8. 图的建立(邻接矩阵)+深度优先遍历+广度优先遍历+Prim算法构造最小生成树(Java语言描述)

    主要参考资料:数据结构(C语言版)严蔚敏   ,http://blog.chinaunix.net/uid-25324849-id-2182922.html   代码测试通过. package 图的建 ...

  9. Prim算法和Kruskal算法求最小生成树

    Prim算法 连通分量是指图的一个子图,子图中任意两个顶点之间都是可达的.最小生成树是连通图的一个连通分量,且所有边的权值和最小. 最小生成树中,一个顶点最多与两个顶点邻接:若连通图有n个顶点,则最小 ...

随机推荐

  1. Js里面的数组去重方法

    去掉数组里面重复的有很多种,我这里就说一种比较简单的吧. var arr=[23,33,44,33,44,66,44,55,44,4,44,33,23]; for(var i=0;i<arr.l ...

  2. OnsenUI和AngularJS配合搭建混合应用的基本步骤

    混合开发的热潮已经掀起,实现混合开发的方式很多.今天给大家介绍一个实现混合开发的基本方法-OnsenUI和AngularJS配合. OnsenUI是一个可以实现混合开发的前端框架,包含了很多前端设计中 ...

  3. Android之万能播放器解码框架Vitamio的介绍及使用

    一.简介 Vitamio能够流畅播放720P甚至1080P高清MKV,FLV,MP4,MOV,TS,RMVB等常见格式的视频,还可以在Android 与 iOS 上跨平台支持 MMS, RTSP, R ...

  4. mysql 索引篇

    一.索引优化   索引优化主要还是依赖explain命令,关于explain命令相信大家并不陌生,具体用法和字段含义可以参考官网explain-output,这里需要强调rows是核心指标,绝大部分r ...

  5. 性能测试平台效率优化的一次经验(python版)

    在做性能测试平台的优化过程中,由于启动任务相对其他测试任务比较频繁,而目前30次两个包的交叉对比(30次)测试需要耗时30分钟整,因此打算优先对测试流程做一次优化,将测试时间消耗降低到20分钟. 由于 ...

  6. C++ Primer 5 CH5 语句

    5.1 简单语句 空语句: ; 5.2 语句作用域 5.3 条件语句 switch 语句:表达式与某个 case 匹配成功,执行 case 之后的语句直到 break 或者 switch 结尾,cas ...

  7. TensorFlow安装-ubuntu

    windows下某些tensorflow例子跑不成功,比如https://www.tensorflow.org/tutorials/wide 中的例子报下面的错误:' 'NoneType' objec ...

  8. Alamofire源码解读系列(十)之序列化(ResponseSerialization)

    本篇主要讲解Alamofire中如何把服务器返回的数据序列化 前言 和前边的文章不同, 在这一篇中,我想从程序的设计层次上解读ResponseSerialization这个文件.更直观的去探讨该功能是 ...

  9. JS调用WebService,发布到IIS,网页提示WebService未定义[已解决]

    VS2013中,JS调用WebService,一直运行正常.部署到WindowsServer2008之后,在网页中访问,始终提示网页中有错误,点开之后发现是WebService未定义. 于是上网查解决 ...

  10. 老李推荐:第5章6节《MonkeyRunner源码剖析》Monkey原理分析-启动运行: 初始化事件源

    老李推荐:第5章6节<MonkeyRunner源码剖析>Monkey原理分析-启动运行: 初始化事件源   poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试 ...