uva 10397(最小生成树)

这道题是最小生成树树的变形。题目告诉你在其中已经添加过了一些边,在剩下的边中选取若干条使其成为一个最小生成树。

我记得上一次做真题是遇到类似的问题。我用了prime算法求解。现在就换用了kruskal算法。

根据查询选把相应边合并,这些边不算入虽小生成树的权值即可,接下来的就和kruskal算法一致。

代码如下:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <cstdlib>
 5 #include <cmath>
 6 #include <algorithm>
 7 #define INF 0x7fffffff
 8 #define LEN 1010
 9 using namespace std;
10 
11 typedef struct{
12     double x, y;
13 }POINT;
14 
15 typedef struct {
16     int a, b;
17     double v;
18 }ARC;
19 
20 int n, m, top, parent[LEN];
21 POINT p[LEN];
22 ARC Arc[LEN*LEN];
23 double Map[LEN][LEN];
24 
25 inline double dis(POINT a, POINT b){return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}
26 bool cmp(ARC a, ARC b){return a.v<b.v;}
27 //UFSet
28 void init() { for(int i=0; i<LEN; i++) parent[i] = i;}
29 int Find(int x){return parent[x]==x?x:parent[x]=Find(parent[x]);}
30 void Union(int a, int b){int pa = Find(a), pb = Find(b);if(pa!=pb)parent[pa] = pb;}
31 
32 double solve()
33 {
34     int q, a, b, cnt = 0;
35     double ans = 0;
36     init();
37     sort(Arc, Arc+top, cmp);
38     scanf("%d", &q);
39     for(int i=0; i<q; i++){
40         scanf("%d%d", &a, &b);
41         if(Find(a)!=Find(b)){
42             Union(a, b);
43 //            ans += Map[a][b];
44             cnt ++;
45         }
46     }
47     for(int i=0; i<top; i++){
48         if(cnt==n-1)break;
49         if(Find(Arc[i].a)!=Find(Arc[i].b)){
50             cnt ++;
51             Union(Arc[i].a, Arc[i].b);
52             ans += Arc[i].v;
53         }
54     }
55     return ans;
56 }
57 
58 int main()
59 {
60 //    freopen("in.txt", "r", stdin);
61 
62     while(scanf("%d", &n)!=EOF)
63     {
64         for(int i=1; i<=n; i++){
65             scanf("%lf%lf", &p[i].x, &p[i].y);
66         }
67         top = 0;
68         for(int i=1; i<=n ;i++){
69             for(int j=i+1; j<=n; j++){
70                 Map[i][j] = Map[j][i] = dis(p[i], p[j]);
71                 Arc[top].a = i;
72                 Arc[top].b = j;
73                 Arc[top].v = dis(p[i], p[j]);
74                 top ++;
75             }
76         }
77         double ans = solve();
78         printf("%.2lf
", ans);
79     }
80     return 0;
81 }
View Code
奔跑吧!少年!趁着你还年轻
原文地址:https://www.cnblogs.com/shu-xiaohao/p/3441688.html