zoukankan      html  css  js  c++  java
  • UVa 10034

      题目大意:给出n个点的坐标(x,y),要求用线段将n个点连接起来,求最小的线段和。

      最小生成树问题,用Kruskal算法进行求解,其中用到了并查集。将所有的点连接,构成一张图,对每一条边进行编号,两点间的距离作为权重。

     1 #include <cstdio>
     2 #include <algorithm>
     3 #include <cmath>
     4 #define square(x) (x)*(x)
     5 #define MAXN 10000
     6 #define POINTN 100+10
     7 using namespace std;
     8 
     9 double w[MAXN], point[POINTN][2];    // the weight of edge
    10 int u[MAXN], v[MAXN], r[MAXN], p[MAXN]; 
    11 // u[i] and v[i] save the end points of the ith edge seperately, r[i] save the ith edge of non-decreasing ordered edges
    12 
    13 double distance(double x1, double y1, double x2, double y2)
    14 {
    15     double t = square(x2-x1) + square(y2-y1);
    16     return sqrt(t);
    17 }
    18 
    19 int cmp(const int i, const int j)
    20 {
    21     return w[i] < w[j];
    22 }
    23 
    24 int find(int x)
    25 {
    26     return p[x] == x ? x : p[x] = find(p[x]);
    27 }
    28 
    29 int main()
    30 {
    31 #ifdef LOCAL
    32     freopen("in", "r", stdin);
    33 #endif
    34     int N;
    35     scanf("%d", &N);
    36     bool first = true;
    37     while (N--)
    38     {
    39         int n;
    40         scanf("%d", &n);
    41         for (int i = 0; i < n; i++)
    42             scanf("%lf%lf", &point[i][0], &point[i][1]);
    43         int k = 0;    // the size of edge
    44         for (int i = 0; i < n; i++)
    45             for (int j = i+1; j < n; j++)
    46             {
    47                 w[k] = distance(point[i][0], point[i][1], point[j][0], point[j][1]);
    48                 u[k] = i;
    49                 v[k] = j;
    50                 k++;
    51             }
    52         double ans = 0;
    53         for (int i = 0; i < n; i++)   p[i] = i;
    54         for (int i = 0; i < k; i++)   r[i] = i;
    55         sort(r, r+k, cmp);    // sort the edge
    56         for (int i = 0; i < k; i++)
    57         {
    58             int e = r[i];
    59             int x = find(u[e]);
    60             int y = find(v[e]);
    61             if (x != y)
    62             {
    63                 ans += w[e];
    64                 p[x] = y;
    65             }
    66         }
    67         if (first)   first = false;
    68         else printf("
    ");
    69         printf("%.2lf
    ", ans);
    70     }
    71     return 0;
    72 }
    View Code

      代码中用到了间接排序——排序的关键字是对象的“代号”,而不是对象本身,将排序后第i小的边的序号保存在r[i]中。这样对象本身的数据就不需要移动了,比如这道题的u[i]和v[i],自己也就能理解到这点了...代码是照抄别人的,解释还是照抄别人的...人工版的Ctrl-C & Ctrl-V 啊...

  • 相关阅读:
    SQL Server中的syscomments表 解析
    char(0)引起的sql2000与sql2005结果不一致
    [转]Winform精耕细作DefWndProc/WndProc/IMessageFilter的区别
    C# 操作并口类,并口通信
    [转]计算机存储单位Byte、KB、MB、GB、TB、PB、EB、ZB、YB、DB、NB
    .net 深入系统编程(三)
    网站随记
    集训final D STL中string的应用
    icpc回顾·暑假
    ie中按钮onclick等事件失效。提示提示对象不支持此操作。在谷歌浏览器中又能使用解决办法
  • 原文地址:https://www.cnblogs.com/xiaobaibuhei/p/3188700.html
Copyright © 2011-2022 走看看