这道题是一颗最小生成树的题目,在一次竞赛中碰到过,当时没做出来,现在学算法了,用的是Prim算法,用java写了写,AC了,放在这,大家一起进步。
import java.text.DecimalFormat;
import java.util.Scanner;
//题目是:Freckles
//这是一道最小生成树题目
public class Poj2560 {
public static void main(String[] args){
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();
double [] x=new double[n];
double[] y=new double[n];
for(int i=0;i<n;i++){
x[i]=sc.nextFloat();
y[i]=sc.nextFloat();
} //输入数据
double [][] a=new double[n][n];
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(i==j) a[i][j]=Double.MAX_VALUE;
else
a[i][j]=Math.sqrt((Math.pow(x[j]-x[i], 2)+Math.pow(y[j]-y[i], 2)));
}
}
double sum2=prim(n,a); //调用Prim算法
DecimalFormat df=new DecimalFormat("0.00");
System.out.println(df.format(sum2));
}
//prim算法
static double prim(int n,double[][] c){
double[] lowcost=new double[n+1]; //记录最小边
int[] closest=new int[n+1]; //记录临接顶点
boolean[] s=new boolean[n+1]; //顶点 标志数组
double sum=0; //记录最短路径长
s[0]=true;
//赋值
for(int i=1;i<n;i++){
lowcost[i]=c[0][i];
closest[i]=0;
s[i]=false;
}
//核心的地方
for(int i=1;i<n;i++){
double min=Double.MAX_VALUE;
int j=0;
for(int k=1;k<n;k++){
if((lowcost[k]<min)&&!s[k]){
min=lowcost[k];
j=k;
}
}
sum+=c[j][closest[j]]; //最短路径长求和
s[j]=true;
//更新lowcost数组和相应closest值
for(int k=1;k<n;k++){
if((c[j][k]<lowcost[k])&&(!s[k])){
lowcost[k]=c[j][k];
closest[k]=j;
}
}
}
return sum;
}
}