zoukankan      html  css  js  c++  java
  • [并查集][最小生成树]Built?

    题目描述

    There are N towns on a plane. The i-th town is located at the coordinates (xi,yi). There may be more than one town at the same coordinates.
    You can build a road between two towns at coordinates (a,b) and (c,d) for a cost of min(|a−c|,|b−d|) yen (the currency of Japan). It is not possible to build other types of roads.
    Your objective is to build roads so that it will be possible to travel between every pair of towns by traversing roads. At least how much money is necessary to achieve this?

    Constraints
    2≤N≤105
    0≤xi,yi≤109
    All input values are integers.

    输入

    Input is given from Standard Input in the following format:

    N
    x1 y1
    x2 y2
    :
    xN yN

    输出

    Print the minimum necessary amount of money in order to build roads so that it will be possible to travel between every pair of towns by traversing roads.

    样例输入

    3
    1 5
    3 9
    7 8
    

    样例输出

    3
    

    提示

    Build a road between Towns 1 and 2, and another between Towns 2 and 3. The total cost is 2+1=3 yen.

     
    思路:用kruscal求最小生成,但是求任意两点构成边的边集会超时(O(n^2));其实不用求C(n,2)条边的距离,只需求2*(n-1)条边的距离——将n个点按x升序排序,得到n-1条相邻点构成边、将n个点按y升序排序,得到n-1条相邻点构成边;则在这2*(n-1)条边的边集上用kruscal一定能找到其中n-1条边构成的最小生成树;
    AC代码:
    #include <iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    typedef long long ll;
    using namespace std;
    
    int fa[200005];
    
    struct Node{
      ll x,y;
      int id;
    }a[100005];//点集
    
    struct Edge{
      int p1,p2;
      ll cost;
    }edge[200005];//边集
    
    bool cmp1(Node a,Node b){ return a.x<b.x; }
    bool cmp2(Node a,Node b){ return a.y<b.y; }
    bool cmp3(Edge a,Edge b){ return a.cost<b.cost; }
    
    int findd(int a){
      if(fa[a]==a) return fa[a];
      else return fa[a]=findd(fa[a]);
    }
    
    int main()
    {
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++) {scanf("%lld%lld",&a[i].x,&a[i].y); a[i].id=i; fa[i]=i;}
        sort(a+1,a+1+n,cmp1);
        int cnt=0;
        for(int i=2;i<=n;i++){
            edge[++cnt].p1=a[i-1].id;
            edge[cnt].p2=a[i].id;
            edge[cnt].cost=a[i].x-a[i-1].x;
        }
        sort(a+1,a+1+n,cmp2);
        for(int i=2;i<=n;i++){
            edge[++cnt].p1=a[i-1].id;
            edge[cnt].p2=a[i].id;
            edge[cnt].cost=a[i].y-a[i-1].y;
        }
        sort(edge+1,edge+1+cnt,cmp3);
        ll ans=0;int num=0;
        for(int i=1;i<=cnt;i++){
            int fa_p1=findd(edge[i].p1);
            int fa_p2=findd(edge[i].p2);
            if(fa_p1==fa_p2) continue;
            else{
                fa[fa_p1]=fa_p2;
                num++;
                ans+=(edge[i].cost);
            }
            if(num==n-1) break;
        }
        printf("%lld
    ",ans);
        return 0;
    }

    相当于kruscal的变形;关键是根据题给的一些性质,对原算法做出一些改变,使原算法得以适用

    转载请注明出处:https://www.cnblogs.com/lllxq/
  • 相关阅读:
    RANSAC算法——RANDOM SAMPLE CONSENSUS
    屏蔽关键词搜索
    全景图拼接——opencv之stitching
    如何 查看本地安装的 .NET Framework(CLR) 版本 方法二亲测可行
    js判断是否是ie浏览器且给出ie版本
    js判断文件大小利用img 的 dynsrc,兼容IE10 及以上
    Java的——String类、StringBuffer和StringBuilder、不可变和可变字符序列使用陷阱
    windows.onload和body的onload属性的区别
    jquery中class选择器的用法,选择两个class
    #JS# 如何判断一个字符串是否为日期格式
  • 原文地址:https://www.cnblogs.com/lllxq/p/9280909.html
Copyright © 2011-2022 走看看