您的位置:首页 > 其它

最小生成树-Prim算法

2017-03-04 22:46 162 查看
题目链接http://acm.whu.edu.cn/learn/problem/detail?problem_id=1038

这是woj里面的一道题目,已知了所有点的坐标,求一条长l的线是否可以将所有的点连接起来。

其主要思路就是采用最小生成树。我们采用Prim算法构造最小生成树。

这道题目中首先利用一个数组来表示节点之间的距离,其中同一节点用无穷大来进行表示。然后调用Prim算法来构造最小生成树

下面看具体代码以及注释,来了解Prim算法

#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#define MAXV 103
#define MAXCOST 0x7fffffff
float quan[MAXV][MAXV];  //存放节点之间的权值
struct{
int x;
int y;
}jiedian[MAXV];  //存放每个节点的横纵坐标

float Prim(float graph[][MAXV],int n){
float lowcost[MAXV];   //表示以i为终点的权值。当lowcost[i]=0时,表示已经加入最小生成树
int mst[MAXV];   //存放lowcost[i]对应的节点
//首先假设第0个节点已经处于最小生成树里面
lowcost[0]=0;
mst[0]=0;
//则lowcost里面存放从第一个节点到最后一个节点到第0个节点的距离
for(int i=1;i<n;i++){
lowcost[i]=quan[0][i];
mst[i]=1;
}
float sum=0;
for(int i=1;i<n;i++){
//从第一个节点开始遍历
float min=MAXCOST;
int minid=0;
for(int j=1;j<n;j++){ //求与该节点最近的点
if(lowcost[j]<min && lowcost[i]!=0){
min=lowcost[i];
mst[i]=j;
}
}
sum+=min;
//更新lowcost
lowcost[minid]=0;
for(int j=1;j<n;j++){
if(lowcost[j]>graph[minid][j]){
lowcost[j]=graph[minid][j];
mst[j]=minid;
}
}

}
return sum;

}
int main(){
int n,l;
while(scanf("%d",&n) && n!=0){
scanf("%d",&l);
for(int i=0;i<n;i++){
scanf("%d %d",&jiedian[i].x,&jiedian[i].y);
}
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
float xx=pow((float)(jiedian[i].x-jiedian[j].x),2)+pow((float)(jiedian[i].y-jiedian[j].y),2); //计算节点之间距离
quan[i][j]=sqrt(xx);
quan[i][i]=MAXCOST;   //相同节点之间距离为无穷大
}
}
float cost=Prim(quan,n);   //求出最小生成树
if(cost<=l) printf("Success!\n");
else printf("Poor magicpig!\n");
}
return 0;
}


总的来说Prim算法主要用到三个数组,其中有一个表示节点直接的权值,一个数组表示目前最小生成树到未加入节点的最短距离,另外一个数组对应这些未加入数组离已加入的节点最近的节点标记。

Prim算法的流程主要是初始化,判断最近节点,更新剩余节点三个步骤一般来说,代码片段中的Prim算法可以直接进行调用。

之后会不断补充有关最小生成树的相关OJ题目来进一步巩固最小生成树
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: