最小生成树问题
先来了解一下最小生成树
在一给定的无向图G = (V, E) 中,(u, v) 代表连接顶点 u 与顶点 v 的边(即),而 w(u, v) 代表此边的权重,若存在 T 为 E 的子集(即)且为无循环图,使得
的 w(T) 最小,则此 T 为 G 的最小生成树。
其实就是来计算最小权的算法,本文用prim算法实现
for (i = 2; i <= n; i++)
{
min = MAXCOST;
minid = 0;
for (j = 2; j <= n; j++)
{
if (lowcost[j] < min && lowcost[j] != 0)
{
min = lowcost[j];//找出权值最短的路径长度
minid = j; //找出最小的ID
}
}
printf("V%d-V%d=%d\n",mst[minid],minid,min);
sum += min;//求和
lowcost[minid] = 0;//该处最短路径置为0
for (j = 2; j <= n; j++)
{
if (graph[minid][j] < lowcost[j])//对这一点直达的顶点进行路径更新
{
lowcost[j] = graph[minid][j];
mst[j] = minid;
}
}
}
printf("最小权值之和=%d\n",sum);
}
现在是不是发现,蓝桥这道题目
完完全全就是典型的最小生成树问题:
#include<iostream>
#include<cmath>
using namespace std;
struct cc{//村庄
int x;
int y;
int h;
};
//所有变量,必须初始化!!!!
double fy(cc x,cc y){//费用
double z=sqrt((x.x-y.x)*(x.x-y.x)+(x.y-y.y)*(x.y-y.y))+(x.h-y.h)*(x.h-y.h);
return z;
}
int main(){
int n;
cin>>n;
cc *a=new cc[n];
for(int i=0;i<n;i++){
cin>>a[i].x>>a[i].y>>a[i].h;
}
double **b=new double*[n];
for(int i=0;i<n;i++){
b[i]=new double[2];
b[i][1]=0;//没有联通
b[i][0]=10000;
}
b[0][0]=0;//距离最小设为0
b[0][1]=1;//1号建发电站,已连接
for(int i=1;i<n;i++){
b[i][0]=fy(a[0],a[i]);
}
// for(int i=0;i<n;i++)
// cout<<b[i][0]<<" "<<b[i][1]<<endl;
int temp=1;
double sum=0;
double min;
int min_i;
while(temp<n){
min=100000;
for(int i=1;i<n;i++){//寻找没有联通的村庄里联通的最小费用
if(b[i][1]==0){
if(min>b[i][0]){
min=b[i][0];
min_i=i;
}
}
}
b[min_i][1]=1;//划为联通的村庄
sum+=b[min_i][0];//划归联通的村庄的费用
for(int i=1;i<n;i++){
if(b[i][1]==0){//没有联通的村庄重新计算联通最小费用
if(b[i][0]>fy(a[min_i],a[i]))
b[i][0]=fy(a[min_i],a[i]);
}
}
temp++;//权值统计
}
printf("%.2f",sum);
return 0;
}