题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1162
意义:给出一些点,用线问使所有点直接或间接连通,需要多长;
思路:裸最小生成树;
法1:
prim算法:MST(Minimum Spanning Tree,最小生成树)问题有两种通用的解法,Prim算法就是其中之一,它是从点的方面考虑构建一颗MST,大致思想是:设图G顶点集合为U,首先任意选择图G中的一点作为起始点a,将该点加入集合V,再从集合U-V中找到另一点b使得点b到V中任意一点的权值最小,此时将b点也加入集合V;以此类推,现在的集合V={a,b},再从集合U-V中找到另一点c使得点c到V中任意一点的权值最小,此时将c点加入集合V,直至所有顶点全部被加入V,此时就构建出了一颗MST。因为有N个顶点,所以该MST就有N-1条边,每一次向集合V中加入一个点,就意味着找到一条MST的边。(这短话复制的别人的,感觉写的蛮好的)
prim算法就是从待选点集中依次选出距离已选点集中距离最小的点加入已选点集中;
代码:
1 #include <iostream> 2 #include <math.h> 3 #include <algorithm> 4 #include <string.h> 5 #include <stdio.h> 6 #define MAXN 100+10 7 #define INF 9999999999 8 using namespace std; 9 10 int n, tag[MAXN]; 11 double mp[MAXN][MAXN], low[MAXN]; 12 13 double prime(void){ 14 memset(tag, 0, sizeof(tag)); //×××标记数组清 0 15 int s=1; 16 double cnt=0; 17 for(int i=1; i<=n; i++){ //×××从点 1 开始 18 low[i]=mp[s][i]; 19 } 20 for(int i=2; i<=n; i++){ 21 double min=INF; 22 for(int j=2; j<=n; j++){ //×××找到未添加点中到以添加点中距离最近的点即当前要添加的点 23 if(!tag[j]&&min>low[j]){ 24 min=low[j]; 25 s=j; 26 } 27 } 28 cnt+=min; //***本题中不存在不能连同的情况,所以不需要加 if(min>=INF) return -1 29 tag[s]=1; 30 for(int j=2; j<=n; j++){ 31 if(!tag[j]&&low[j]>mp[s][j]){ //×××更新low数组 32 low[j]=mp[s][j]; 33 } 34 } 35 } 36 return cnt; 37 } 38 39 int main(void){ 40 while(~scanf("%d", &n)){ 41 pair<double, double> p[MAXN]; 42 for(int i=1; i<=n; i++){ 43 scanf("%lf%lf", &p[i].first, &p[i].second); 44 } 45 for(int i=1; i<=n; i++){ 46 for(int j=1; j<=n; j++){ 47 mp[i][j]=sqrt((p[j].first-p[i].first)*(p[j].first-p[i].first)+(p[j].second-p[i].second)*(p[j].second-p[i].second)); 48 } 49 } 50 double ans=prime(); 51 printf("%.2lf\n", ans); 52 } 53 return 0; 54 }