• [BZOJ] 1626: [Usaco2007 Dec]Building Roads 修建道路


    1626: [Usaco2007 Dec]Building Roads 修建道路

    Time Limit: 5 Sec  Memory Limit: 64 MB
    Submit: 1724  Solved: 725
    [Submit][Status][Discuss]

    Description

    Farmer John最近得到了一些新的农场,他想新修一些道路使得他的所有农场可以经过原有的或是新修的道路互达(也就是说,从任一个农场都可以经过一些首尾相连道路到达剩下的所有农场)。有些农场之间原本就有道路相连。 所有N(1 <= N <= 1,000)个农场(用1..N顺次编号)在地图上都表示为坐标为(X_i, Y_i)的点(0 <= X_i <= 1,000,000;0 <= Y_i <= 1,000,000),两个农场间道路的长度自然就是代表它们的点之间的距离。现在Farmer John也告诉了你农场间原有的M(1 <= M <= 1,000)条路分别连接了哪两个农场,他希望你计算一下,为了使得所有农场连通,他所需建造道路的最小总长是多少。

    Input

    * 第1行: 2个用空格隔开的整数:N 和 M

     * 第2..N+1行: 第i+1行为2个用空格隔开的整数:X_i、Y_i * 第N+2..N+M+2行: 每行用2个以空格隔开的整数i、j描述了一条已有的道路, 这条道路连接了农场i和农场j

    Output

    * 第1行: 输出使所有农场连通所需建设道路的最小总长,保留2位小数,不必做 任何额外的取整操作。为了避免精度误差,计算农场间距离及答案时 请使用64位实型变量

    Sample Input

    4 1
    1 1
    3 1
    2 3
    4 3
    1 4

    输入说明:

    FJ一共有4个坐标分别为(1,1),(3,1),(2,3),(4,3)的农场。农场1和农场
    4之间原本就有道路相连。


    Sample Output

    4.00

    输出说明:

    FJ选择在农场1和农场2间建一条长度为2.00的道路,在农场3和农场4间建一
    条长度为2.00的道路。这样,所建道路的总长为4.00,并且这是所有方案中道路
    总长最小的一种。

    HINT

     

    Source

    Silver

    Analysis

     最小生成树的水题

    如果有一些农场已经互相连接了 -- 那就提前 unite

    注意计算坐标时是否溢出

    Code

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cmath>
     4 #include<algorithm>
     5 #define maxn 2000
     6 using namespace std;
     7 
     8 int n,m,x[maxn],y[maxn];
     9 
    10 int pre[maxn];
    11 int find(int x){
    12     if(!pre[x]) return x;
    13     else{
    14         pre[x] = find(pre[x]);
    15         return pre[x];
    16     }
    17 }void unite(int a,int b){
    18     if(find(a) != find(b)) pre[find(a)] = find(b);
    19 }
    20 
    21 struct edge{
    22     int u,v;
    23     double len;
    24 }e[maxn*maxn];
    25 
    26 int tot;
    27 void insert(int u,int v,double len){
    28     tot++;
    29     e[tot].u = u;
    30     e[tot].v = v;
    31     e[tot].len = len;
    32 }
    33 
    34 double getdis(int a,int b){
    35     return sqrt(1LL*(x[a]-x[b])*(x[a]-x[b])+1LL*(y[a]-y[b])*(y[a]-y[b]));
    36 }
    37 
    38 bool cmp(const edge &a,const edge &b){
    39     return a.len < b.len;
    40 }
    41 
    42 void kruskal(){
    43     sort(e+1,e+1+tot,cmp);
    44     
    45     double ans = 0;
    46     
    47     for(int i = 1;i <= tot;i++){
    48         int u = e[i].u,v = e[i].v;
    49         if(find(u) != find(v)){
    50             unite(u,v);
    51             ans += e[i].len;
    52         }
    53     }
    54     
    55     printf("%.2lf",ans);
    56 }
    57 
    58 int main(){
    59     scanf("%d%d",&n,&m);
    60     
    61     for(int i = 1;i <= n;i++){
    62         scanf("%d%d",&x[i],&y[i]);
    63     }
    64     
    65     for(int i = 1;i <= m;i++){
    66         int a,b;
    67         scanf("%d%d",&a,&b);
    68         unite(a,b);
    69     }
    70     
    71     for(int i = 1;i <= n;i++){
    72         for(int j = i+1;j <= n;j++){
    73             if(find(i) != find(j)){
    74                 insert(i,j,getdis(i,j));
    75             }
    76         }
    77     }
    78     
    79     kruskal();
    80     
    81     return 0;
    82 }
    Kruskal嗯
    转载请注明出处 -- 如有意见欢迎评论
  • 相关阅读:
    设计模式的读书笔记
    腾讯历年笔试题
    原始套接字的简单tcp包嗅探
    一些有意思,有深度,容易错的代码收集
    sizeof的用法的一些归纳
    一道有趣的题目
    C++的一些设计注意点
    Gazebo Ros入门
    机器学习之多变量线性回归(Linear Regression with multiple variables)
    机器学习之单变量线性回归(Linear Regression with One Variable)
  • 原文地址:https://www.cnblogs.com/Chorolop/p/7466686.html
Copyright © 2020-2023  润新知