题意:
就是裸的最小生成树(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 ", 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 ", 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 ", ans); 82 } 83 return 0; 84 }