关于prim 算法在我写的另一篇中做了详细解释。
http://blog.csdn.net/oceanlight/article/details/7885941
此题是裸的最小生成树,比较容易。不过第一次写,不熟,写错了一处,一直wa。。。。
此题的图是个完全图 E = V*(V-1)/2;
prim 朴素的算法是 O(V^2)
而kruskal 算法 是 O(ElgE) ,因为是完全图,是稠密图,效率不如 prim
第一次写prim算法 : 自己写的被一个细节wa 爆了 。。。。。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cmath>
using namespace std;
int n ;
double adj[110][110]; // 邻接矩阵
bool vis[110];
double dis[110];
struct Node {
double x;
double y;
} node [110];
double cal_length (Node a,Node b){
double len = (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
return sqrt(len);
}
void init_adj(){
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
adj[i][j] = cal_length(node[i],node[j]);
}
}
}
double cal_min_len(){ // 求最小生成树的 最小权值的和
for(int i =1 ;i<=n;i++){
dis[i] = adj[1][i];
vis[i] = false;
}
int st = 1;
vis[st] = true;
double len_sum =0;
int idx =0;
for(int i =2;i<=n;i++){
for(int j =1 ;j<=n;j++){
if(!vis[j]){
if(dis[j]>adj[st][j]){
dis[j]=adj[st][j];
}
}
}
double minlen = 500000000.0;
for(int j =1 ;j<=n;j++){
if(!vis[j]){
if(dis[j]<minlen){
minlen = dis[j];
idx = j;
}
}
}
len_sum += minlen;
st =idx ;
vis[st] = true;
}
return len_sum;
}
int main(){
int cas = 1;
while(true){
scanf("%d",&n);
if(n==0)
break;
for(int i=1;i<=n;i++){
double x , y ;
scanf("%lf%lf",&x,&y);
node[i].x = x ;
node[i].y = y ;
}
init_adj();
if(cas>1)
cout <<endl; //注意题目要求输出 没两组输出空行
printf("Case #%d:\nThe minimal distance is: %.2lf\n",cas,cal_min_len());// 注意输出格式
cas++;
}
}