最小生成树MST
不懂什么是最小生成树的可以看-->这个博客
Prim 适合点少
此算法可以称为”加点法“,每次迭代选择代价最小的边对应的点,加入到最小生成树中。
Kruskal 适合边少
此算法可以称为“加边法”,初始最小生成树边数为0,每迭代一次就选择一条满足条件的最小代价边,加入到最小生成树的边集合里。
(感觉就是并查集)
某省调查乡村交通状况,得到的统计表中列出了任意两村庄间的距离。省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可),并要求铺设的公路总长度为最小。请计算最小的公路总长度。
Input
测试输入包含若干测试用例。每个测试用例的第1行给出村庄数目N ( < 100 );随后的N(N-1)/2行对应村庄间的距离,每行给出一对正整数,分别是两个村庄的编号,以及此两村庄间的距离。为简单起见,村庄从1到N编号。
当N为0时,输入结束,该用例不被处理。
当N为0时,输入结束,该用例不被处理。
Prim
156ms 1424k
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream>
2 #include <cstdio>
3 #include <cstring>
4 using namespace std;
5 #define mem(a) memset(a,0,sizeof(a))
6 #define ll long long
7
8 const int inf = 0x3f3f3f3f;
9 const int maxn = 110;
10
11 int map[maxn][maxn];
12 bool vis[maxn];
13 int dis[maxn];
14 int n;
15 void init()
16 {
17 for(int i = 1; i <= 100; i++)
18 for(int j = 1; j <= 100; j++)
19 if(i==j) map[i][j] = 0;
20 else map[i][j] = inf;
21 }
22
23 int prim()
24 {
25 int ans = 0;
26 for(int i = 1; i <= n; i++)
27 dis[i] = map[1][i];
28 mem(vis);
29 vis[1] = 1;
30 int k;
31 for(int i = 2; i <= n; i++)
32 {
33 int min = inf;
34 for(int j = 1; j <= n; j++)
35 if(!vis[j] && min > dis[j])
36 {
37 min = dis[j];
38 k = j;
39 }
40 vis[k] = 1;
41 ans += min;
42 for(int j = 1; j <= n; j++)
43 {
44 if(!vis[j] && dis[j] > map[k][j])
45 dis[j] = map[k][j];
46 }
47 }
48 return ans;
49 }
50
51 int main()
52 {
53 while(scanf("%d",&n)&&n)
54 {
55 int m = n*(n-1)/2;
56 init();
57 int u,v,val;
58 for(int i = 1; i <= m; i++)
59 {
60 scanf("%d%d%d",&u,&v,&val);
61 map[u][v] = map[v][u] = val;
62 }
63 int ans = prim();
64 printf("%d\n",ans);
65 }
66 return 0;
67 }
Kruskal
187ms 1456k
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream>
2 #include <cstdio>
3 #include <cstring>
4 #include <algorithm>
5 using namespace std;
6 #define mem(a) memset(a,0,sizeof(a))
7 #define ll long long
8 const int maxn = 100100;
9 struct node
10 {
11 int u,v,val;
12 }a[maxn];
13
14 int pre[110];
15
16 bool cmp(node a,node b)
17 {
18 return a.val < b.val;
19 }
20
21 int find(int x)
22 {
23 if(x == pre[x])
24 return x;
25 return pre[x] = find(pre[x]);
26 }
27
28 void unite(int x,int y)
29 {
30 x = find(x);
31 y = find(y);
32 pre[y] = x;
33 }
34
35 int main()
36 {
37 int n;
38 while(scanf("%d",&n)&&n)
39 {
40 int m = n*(n-1)/2;
41 for(int i = 1; i <= n; i++) pre[i] = i;
42 for(int i = 0; i < m; i++)
43 scanf("%d%d%d",&a[i].u,&a[i].v,&a[i].val);
44 sort(a,a+m,cmp);
45 int ans = 0;
46 for(int i = 0; i < m; i++)
47 {
48 if(find(a[i].u)!=find(a[i].v))
49 {
50 unite(a[i].u,a[i].v);
51 ans += a[i].val;
52 }
53 }
54 printf("%d\n",ans);
55 }
56 return 0;
57 }
相信大家都听说一个“百岛湖”的地方吧,百岛湖的居民生活在不同的小岛中,当他们想去其他的小岛时都要通过划小船来实现。现在政府决定大力发展百岛湖,发展首先要解决的问题当然是交通问题,政府决定实现百岛湖的全畅通!经过考察小组RPRush对百岛湖的情况充分了解后,决定在符合条件的小岛间建上桥,所谓符合条件,就是2个小岛之间的距离不能小于10米,也不能大于1000米。当然,为了节省资金,只要求实现任意2个小岛之间有路通即可。其中桥的价格为 100元/米。
Input
输入包括多组数据。输入首先包括一个整数T(T <= 200),代表有T组数据。
每组数据首先是一个整数C(C <= 100),代表小岛的个数,接下来是C组坐标,代表每个小岛的坐标,这些坐标都是 0 <= x, y <= 1000的整数。
Output
每组输入数据输出一行,代表建桥的最小花费,结果保留一位小数。如果无法实现工程以达到全部畅通,输出”oh!”.
Prim
15ms 1432k
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <bits/stdc++.h>
2 using namespace std;
3
4 #define mem(a) memset(a,0,sizeof(a))
5 #define ll long long
6
7 const int maxn = 110;
8 const double inf = 100000.1;
9 double dis[maxn];//距离
10 bool vis[maxn];//标记数组
11 double ans;//答案
12 int n;//n个岛
13
14 struct node
15 {
16 int x,y;
17 } a[maxn];
18
19 double dist(int i,int j)
20 {
21 int dx = a[i].x-a[j].x;
22 int dy = a[i].y-a[j].y;
23 return sqrt((double)(dx*dx+dy*dy));
24 }
25
26 void prim()
27 {
28 int k = 0;
29 for(int i = 1; i < n; i++)
30 {
31 if(dist(k,i) >= 10.0 && dist(k,i) <= 1000.0)
32 dis[i] = dist(0,i);
33 else
34 dis[i] = inf;
35 }
36 mem(vis);
37 vis[k] = 1;
38 ans = 0;
39 for(int i = 1; i < n; i++)
40 {
41 double min = inf;
42 for(int j = 0; j < n; j++)
43 {
44 if(!vis[j] && min>dis[j])
45 {
46 if(dis[j] >= 10.0 && dis[j] <= 1000.0)
47 {
48 min = dis[j];
49 k = j;
50 }
51 }
52 }
53 if(min < inf)
54 {
55 ans += min;
56 vis[k] = 1;
57 }
58 for(int j = 0; j < n; j++)
59 {
60 if(!vis[j] && dis[j] > dist(k,j))
61 {
62 if(dist(k,j) >= 10.0 && dist(k,j) <= 1000.0)
63 dis[j] = dist(k,j);
64 }
65 }
66 }
67 }
68
69 int main()
70 {
71 ios::sync_with_stdio(false);
72 cin.tie(0),cout.tie(0);
73 int t;
74 cin>>t;
75 while(t--)
76 {
77 cin>>n;
78 for(int i = 0; i < n; i++)
79 cin>>a[i].x>>a[i].y;
80
81 prim();
82
83 bool flag = true;
84 for(int i = 0; i < n; i++)
85 {
86 if(!vis[i])
87 {
88 flag = false;
89 }
90 }
91 if(flag)
92 printf("%.1f\n",ans*100);
93 else
94 printf("oh!\n");
95 }
96 }
Kruskal
78ms 1524k
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream>
2 #include <cstdio>
3 #include <cstring>
4 #include <algorithm>
5 #include <cmath>
6 using namespace std;
7
8 #define mem(a) memset(a,0,sizeof(a))
9 #define ll long long
10 const int maxn = 110;
11 int pre[maxn];
12
13 struct node
14 {
15 int x,y;
16 } a[maxn];
17
18 struct m
19 {
20 int u,v;
21 double val;
22 } b[5100];
23
24 int find(int x)
25 {
26 if(x == pre[x])
27 return x;
28 return pre[x] = find(pre[x]);
29 }
30
31 void unite(int x,int y)
32 {
33 x = find(x);
34 y = find(y);
35 pre[y] = x;
36 }
37
38 double dis(int i,int j)
39 {
40 int dx = a[i].x - a[j].x;
41 int dy = a[i].y - a[j].y;
42 return sqrt((double)(dx*dx+dy*dy));
43 }
44
45 bool cmp(m x,m y)
46 {
47 return x.val < y.val;
48 }
49
50 int main()
51 {
52 ios::sync_with_stdio(false);
53 cin.tie(0),cout.tie(0);
54 int t,n;
55 cin>>t;
56 while(t--)
57 {
58 cin>>n;
59 for(int i = 0; i < n; i++)
60 {
61 cin>>a[i].x>>a[i].y;
62 pre[i] = i;
63 }
64 int k = 0;
65 for(int i = 0; i < n; i++)
66 {
67 for(int j = i+1; j < n; j++)
68 {
69 b[k].u = i;
70 b[k].v = j;
71 b[k].val = dis(i,j);
72 k++;
73 }
74 }
75 sort(b,b+k,cmp);
76 double ans = 0;
77 for(int i = 0; i < k; i++)
78 {
79 if(find(b[i].u) != find(b[i].v))
80 {
81 if(b[i].val >= 10.0 && b[i].val <= 1000.0)
82 {
83 ans += b[i].val;
84 unite(b[i].u,b[i].v);
85 }
86 }
87 }
88 bool flag = true;
89 int temp = find(0);
90 for(int i = 1; i < n; i++)
91 {
92 if(find(i) != temp)
93 {
94 flag = false;
95 break;
96 }
97 }
98 if(flag)
99 printf("%.1f\n",ans*100);
100 else
101 printf("oh!\n");
102 }
103 return 0;
104 }