6569: Built?(Kruskal, 坐标中的点进行构图)

6569: Built?

时间限制: 1 Sec  内存限制: 128 MB
提交: 113  解决: 57
[提交] [状态] [讨论版] [命题人:admin]

题目描述

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条边构成的最小生成树;

//Sinhaeng Hhjian
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<vector>
#include<stdlib.h>
#include<math.h>
#include<set>
#include<algorithm>
using namespace std;
typedef long long ll;
const int mod = 1e9+7;
const int maxn = 1e5+5;
int fa[maxn];
struct Node{
  ll x, y, id;
}st[maxn];

struct Edge{
  ll cost, p1, p2;
}edge[maxn*2];

int cmp1(Node a,Node b){ 
	return a.x<b.x; 
}
int cmp2(Node a,Node b){ 
	return a.y<b.y; 
}
int cmp3(Edge a,Edge b){ 
	return a.cost<b.cost; 
}

int find(int u){
  	if(fa[u]==u) 
  		return fa[u];
  	return fa[u]=find(fa[u]);
}

int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++) {
		scanf("%lld%lld", &st[i].x, &st[i].y); 
		st[i].id=i; 
		fa[i]=i;
	}
    sort(st+1,st+1+n,cmp1);
    int cnt=0;
    for(int i=2;i<=n;i++){
        edge[++cnt].p1=st[i-1].id;
        edge[cnt].p2=st[i].id;
        edge[cnt].cost=st[i].x-st[i-1].x;
    }
    sort(st+1,st+1+n,cmp2);
    for(int i=2;i<=n;i++){
        edge[++cnt].p1=st[i-1].id;
        edge[cnt].p2=st[i].id;
        edge[cnt].cost=st[i].y-st[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=find(edge[i].p1);
        int fa_p2=find(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\n",ans);
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hhjian6666

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值