UvaLive 4872 Underground Cables (最小生成树)

题意:

就是裸的最小生成树(MST), 完全图, 边长是实数。

分析:

算是复习一下MST把

方法一: prim 复杂度(n^2)

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int maxn = 1e3 + 7;
 4 const int inf = 0x3f3f3f3f;
 5 double G[maxn][maxn], dis[maxn];
 6 bool vis[maxn];
 7 int x[maxn], y[maxn];
 8 int N;
 9 double p2pdis(int x1, int y1, int x2, int y2){
10     double dis = sqrt((x1-x2) * (x1 - x2) + (y1-y2) * (y1-y2));
11     return dis;
12 }
13 int main(){
14     #if LOCAL
15     freopen("1.txt","r",stdin);
16     #endif // LOCAL
17 
18     while(scanf("%d", &N) && N){
19         memset(G,0,sizeof(G));
20         memset(vis,0,sizeof(vis));
21         for(int i = 0; i < N; i++){
22             scanf("%d %d", &x[i], &y[i]);
23         }
24 
25         for(int i = 0; i < N; i++){
26             for(int j = 0; j < N; j++){
27                 if(j != i){
28                     G[i][j] = p2pdis(x[i],y[i],x[j],y[j]);
29                 }
30             }
31         }
32         
33         double ans = 0;
34         
35         vis[0] = 1;
36         for(int i = 0; i < N; i++){
37             dis[i] = G[0][i]; //一开始起点加入树中, 所以可以将dis初始化为起点的出边
38         }
39         
40         
41         
42         for(int i = 0; i < N - 1;i++){//除去起点, 还剩n-1个点不在生成树中
43            double mind = inf;
44            int j,sel;
45            for(j = 0; j < N; j++){
46                 if(!vis[j] && dis[j] < mind){
47                     mind = dis[j];
48                     sel = j;
49                 }
50            }
51            vis[sel] = 1;
52            ans += dis[sel];
53            for(int k = 0; k < N; k++){
54                 if(!vis[k] && dis[k] > G[sel][k]){
55                     dis[k] = G[sel][k]; //注意这里 prim是更新dis到选中点出边距离, dij是更新dis[选中点] + 选中点出边距离
56                 }
57            }
58         }
59         printf("%.2f\n", ans);
60     }
61 }

方法二: kruskal 复杂度(MlogM)

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 int N;
 4 const int maxn = 1e3 + 7;
 5 const int inf = 0x3f3f3f3f;
 6 
 7 struct edge{
 8     int u;
 9     int v;
10     double d;
11     friend bool operator< (edge n1,edge n2){
12         return n1.d<n2.d;
13     }
14 }
15 ;
16 edge m[maxn*maxn];
17 
18 
19 
20 double dis[maxn];
21 bool vis[maxn];
22 int x[maxn], y[maxn], f[maxn];
23 
24 int getf(int v){
25     if(f[v] == v)
26         return v;
27     else{
28         f[v] = getf(f[v]);
29         return f[v];
30     }
31 }
32 int mer(int v, int u){
33     int t1, t2;
34     t1 = getf(v);
35     t2 = getf(u);
36     if(t1 != t2){
37         f[t2] = t1;
38         return 1;
39     }
40     return 0;
41 }
42 
43 double p2pdis(int x1, int y1, int x2, int y2){
44     double dis = sqrt((x1-x2) * (x1 - x2) + (y1-y2) * (y1-y2));
45     return dis;
46 }
47 int main(){
48 
49     while(scanf("%d", &N) && N){
50         memset(vis,0,sizeof(vis));
51         for(int i = 0; i < N; i++){
52             scanf("%d %d", &x[i], &y[i]);
53         }
54 
55         int mcnt = 0;
56         for(int i = 0; i < N; i++){
57             for(int j = 0; j < N; j++){
58                 if(j != i){
59                     m[mcnt].u = i;
60                     m[mcnt].v = j;
61                     m[mcnt++].d = p2pdis(x[i],y[i],x[j],y[j]);
62                 }
63             }
64         }
65         sort(m,m+mcnt); //从小到大排序边
66 
67         for(int i = 0; i < N; i ++){//并查集初始化
68             f[i] = i;
69         }
70         double ans = 0;
71         int cnt = 0;
72         for(int i = 0; i < mcnt; i++){//从小到大枚举
73             if(mer(m[i].u, m[i].v)){
74 //                printf("u: %d v: %d\n", m[i].u, m[i]. v);
75                 cnt ++;
76                 ans += m[i].d;
77             }
78             if( cnt == N - 1)//用了n-1条边后退出
79                 break;
80         }
81         printf("%.2f\n", ans);
82     }
83         return 0;
84 }

 

posted @ 2017-07-28 15:53  Neord  阅读(144)  评论(0编辑  收藏  举报