import java.util.Scanner;
public class Test {
/*
*求最小生成树的prim算法
*其中,weight中存储的是图中每条边的代价,如果两点之间不存在边则存储-1。
* lowcost存储的是当前选出的节点到未选中节点的最短距离
* closeset记录了当前最短距离是从哪个被选中的节点产生的
* used记录了节点是否被选出来了,true代表已选中。
*/
public static void main(String[] args){
Scanner reader = new Scanner(System.in);
int n = reader.nextInt();
int[][] weight = new int[n+1][n+1];
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
weight[i][j] = reader.nextInt();
}
}
int[] lowcost = new int[n+1];
int[] closeset = new int[n+1];
boolean[] used = new boolean[n+1];
used[1] = true;
for(int i=2;i<=n;i++){
lowcost[i] = weight[1][i];
closeset[i] = 1;
}
for(int i=2;i<=n;i++){
int min = Integer.MAX_VALUE;
int j=1;
for(int k=2;k<=n;k++){//选择当前已选中节点到未选中节点的所有路径中最小的一条路径
if(lowcost[k]!=-1&&lowcost[k]<min&&!used[k]){
min = lowcost[k];
j = k;
}
}
used[j] = true;
System.out.println(closeset[j]+"---->"+j+" 路径长为:"+min);//最小路径是从closeset出发的。
for(int k=2;k<=n;k++){//因为新加入了j节点,所以需要更新lowcost。
if((weight[j][k]<lowcost[k]||lowcost[k]==-1)&&!used[k]){
lowcost[k] = weight[j][k];
closeset[k] = j;
}
}
}
}
}
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;
import java.util.TreeSet;
public class Test {
/*
*求最小生成树的kruskal算法
*算法思想:首先将每条边按照代价从低到高排序,依次选择代价最小的边,
*如果这条边的两个顶点不在同一个连通分量,则将该边加入最小生成树中,
*直到所有的顶点都在一个连通分量中。
*/
public static void main(String[] args){
GraphInit graph = new GraphInit();
int[] points = graph.initPoint();
ArrayList<Edge> edges = graph.initEdge();
Collections.sort(edges);
ArrayList<HashSet<Integer>> sets = new ArrayList<>();//记录连通分量
for(int i=0;i<points.length;i++){//首先初始化,每个顶点都单独在一个连通分量中。
HashSet<Integer> set = new HashSet<>();
set.add(points[i]);
sets.add(set);
}
int totalDistance = 0;
for(Edge edge:edges){//依次检查每条边
int start = edge.start;
int end = edge.end;
int start_index = -1,end_index = -1;
for(int i=0;i<sets.size();i++){//找到该条边的两个顶点是否在一个连通分量中。
if(sets.get(i).contains(start))
start_index = i;
if(sets.get(i).contains(end))
end_index = i;
if(start_index>=0&&end_index>=0)
break;
}
if(start_index!=end_index){//如果不在一个连通分量中,将该条边加入到结果集中,并且将两个连通分量合并成一个连通分量
System.out.println(edge.toString());
totalDistance += edge.distance;
HashSet<Integer> startSet = sets.get(start_index);
HashSet<Integer> endSet = sets.get(end_index);
sets.remove(startSet);
sets.remove(endSet);
startSet.addAll(endSet);//合并连通分量
sets.add(startSet);
}
if(sets.size()==1){//如果只剩下一个连通分量,结束。
break;
}
}
System.out.println(totalDistance);
}
}
/*
* 图的初始化类
*/
class GraphInit{
public final int pointNums = 5;
public int[] initPoint(){//初始化顶点
return new int[]{1,2,3,4,5};
}
public ArrayList<Edge> initEdge(){//初始化边
ArrayList<Edge> edges = new ArrayList<>();
edges.add(new Edge(1,2,1));
edges.add(new Edge(1,3,2));
edges.add(new Edge(1,4,3));
edges.add(new Edge(2,3,2));
edges.add(new Edge(3,4,4));
edges.add(new Edge(3,5,3));
edges.add(new Edge(4,5,2));
return edges;
}
}
/*
* 边类
* 实现了comparable接口
*/
class Edge implements Comparable<Edge>{
public int start;
public int end;
public int distance;
public Edge(int start,int end,int distance){
this.start = start;
this.end = end;
this.distance = distance;
}
@Override
public String toString(){
return start+"-->"+end;
}
@Override
public int compareTo(Edge object){
return this.distance>object.distance?1:(this.distance==object.distance?0:-1);
}
}