复习。
借图= =
n个点,给出两两点之间的距离,求最小生成树的边长度之和。
稠密图,用prim。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![ExpandedBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include <iostream>
2 #include <cmath>
3 #include <cstring>
4 #include <iomanip>
5 using namespace std;
6
7 const double maxd = 1000001;
8 const int N = 105;
9
10 double x[N], y[N];
11 double map1[N][N], dis[N];
12 int vis[N];
13
14 double cal( int i, int j)
15 {
16 double ret = (y[i] - y[j]) * (y[i] - y[j]) + (x[i] - x[j]) * (x[i] - x[j]);
17 return sqrt(ret);
18 }
19
20 void input( int n)
21 {
22 for( int i= 1; i<=n; i++)
23 cin >> x[i] >> y[i];
24 for( int i= 1; i<=n; i++)
25 {
26 map1[i][i] = maxd;
27 for( int j=i+ 1; j<=n; j++)
28 map1[i][j] = map1[j][i] = cal(i,j);
29 }
30 }
31
32 /*
33 *代码思路:已一个点为起点,找n-1次,每次添加一个点进入结果集
34 *dis[i]维护结果集与i点的最短距离
35 *vis[i]代表点i是否已加入结果集
36 *
37 */
38 double prim( int n)
39 {
40 double ret = 0;
41 int cur = 1;
42 for( int i= 1; i<=n; i++) dis[i] = maxd;
43 memset(vis, 0, sizeof(vis));
44 dis[cur] = 0; vis[cur] = 1;
45 // 找n-1轮
46 for( int i= 1; i<n; i++)
47 {
48 // 枚举上一次加入的点与各个点的距离,更新最小距离dis[i]
49 for( int j= 1; j<=n; j++)
50 {
51 if(vis[j]== 0 && dis[j]>map1[cur][j])
52 dis[j] = map1[cur][j];
53 }
54 // 选出最短的边,把该边连接的点加入结果集
55 double mind = maxd;
56 for( int j= 1; j<=n; j++)
57 {
58 if(vis[j]== 0 && dis[j]<mind)
59 {
60 mind = dis[j];
61 cur = j;
62 }
63 }
64 vis[cur] = 1;
65 ret += mind;
66 // cout << i << ": " << mind << endl;
67 }
68 return ret;
69 }
70
71 int main()
72 {
73 int Case = 1, n;
74 while(cin >> n)
75 {
76 if(n== 0) break;
77 input(n);
78 double ans = prim(n);
79
80 if(Case> 1) cout << endl;
81 cout << " Case # " << Case++ << " : " << endl;
82 cout << " The minimal distance is: ";
83 cout << setiosflags(ios:: fixed) << setprecision( 2) << ans << endl;
84 }
85 return 0;
86 }
2 #include <cmath>
3 #include <cstring>
4 #include <iomanip>
5 using namespace std;
6
7 const double maxd = 1000001;
8 const int N = 105;
9
10 double x[N], y[N];
11 double map1[N][N], dis[N];
12 int vis[N];
13
14 double cal( int i, int j)
15 {
16 double ret = (y[i] - y[j]) * (y[i] - y[j]) + (x[i] - x[j]) * (x[i] - x[j]);
17 return sqrt(ret);
18 }
19
20 void input( int n)
21 {
22 for( int i= 1; i<=n; i++)
23 cin >> x[i] >> y[i];
24 for( int i= 1; i<=n; i++)
25 {
26 map1[i][i] = maxd;
27 for( int j=i+ 1; j<=n; j++)
28 map1[i][j] = map1[j][i] = cal(i,j);
29 }
30 }
31
32 /*
33 *代码思路:已一个点为起点,找n-1次,每次添加一个点进入结果集
34 *dis[i]维护结果集与i点的最短距离
35 *vis[i]代表点i是否已加入结果集
36 *
37 */
38 double prim( int n)
39 {
40 double ret = 0;
41 int cur = 1;
42 for( int i= 1; i<=n; i++) dis[i] = maxd;
43 memset(vis, 0, sizeof(vis));
44 dis[cur] = 0; vis[cur] = 1;
45 // 找n-1轮
46 for( int i= 1; i<n; i++)
47 {
48 // 枚举上一次加入的点与各个点的距离,更新最小距离dis[i]
49 for( int j= 1; j<=n; j++)
50 {
51 if(vis[j]== 0 && dis[j]>map1[cur][j])
52 dis[j] = map1[cur][j];
53 }
54 // 选出最短的边,把该边连接的点加入结果集
55 double mind = maxd;
56 for( int j= 1; j<=n; j++)
57 {
58 if(vis[j]== 0 && dis[j]<mind)
59 {
60 mind = dis[j];
61 cur = j;
62 }
63 }
64 vis[cur] = 1;
65 ret += mind;
66 // cout << i << ": " << mind << endl;
67 }
68 return ret;
69 }
70
71 int main()
72 {
73 int Case = 1, n;
74 while(cin >> n)
75 {
76 if(n== 0) break;
77 input(n);
78 double ans = prim(n);
79
80 if(Case> 1) cout << endl;
81 cout << " Case # " << Case++ << " : " << endl;
82 cout << " The minimal distance is: ";
83 cout << setiosflags(ios:: fixed) << setprecision( 2) << ans << endl;
84 }
85 return 0;
86 }
注意算法思想与代码思路。。