问题 D: Built?

问题 D: Built?

时间限制: 1 Sec  内存限制: 128 MB
提交: 88  解决: 46
[提交] [状态] [讨论版] [命题人: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.

看半天看不懂,safufu的,给你一堆点(x,y),修路,最小生成树嘛

每两个点之间的花费是min(abs(x1-x2),abs(y1-y2))

这样你要是每个点都和其他的点建立一个边的话,那数据量可就大了去了,

这样,随便拿出一个点(x,y)是不是找距离他最近的点建边比较好?(按照Kruaskal考虑,最短的边优先考虑)

那么就按这个点x的左右最近的点建边,y的上下最近的点建边,也就是说一个点建了4条边

这样一遍Kruaskal就可以啦

#include<bits/stdc++.h>
using namespace std;
#define N 100005
int n;
struct edg{
    int x,y,i;
}Edg[N],Te[N];
struct node{
    int from,to,spend;
    bool operator < (const node &a) const{///写cmp函数也行
        return spend<a.spend;
    }
}Nod[N*10];
bool cmp(edg a,edg b){
    return a.x<b.x;
}
bool cmp2(edg a,edg b){
    return a.y<b.y;
}
int book[N];
int Find(int x){
    if(x==book[x])
        return x;
    return book[x]=Find(book[x]);
}
void Copy(){
    for(int i=1;i<=n;i++)
        Te[i]=Edg[i];
}
int main()
{
    scanf("%d",&n);

    for(int i=1;i<=n;i++)
        scanf("%d%d",&Edg[i].x,&Edg[i].y),Edg[i].i=i;

    Copy();
    sort(Te+1,Te+1+n,cmp);

    int m = 0;///共建立m条边

    for(int i=1;i<n;i++)
        Nod[++m].from = Te[i].i,Nod[m].to = Te[i+1].i,Nod[m].spend = min(abs(Te[i].x-Te[i+1].x),abs(Te[i].y-Te[i+1].y));

    Copy();
    sort(Te+1,Te+1+n,cmp2);

    for(int i=1;i<n;i++)
        Nod[++m].from = Te[i].i,Nod[m].to = Te[i+1].i,Nod[m].spend = min(abs(Te[i].x-Te[i+1].x),abs(Te[i].y-Te[i+1].y));

    sort(Nod+1,Nod+1+m);

    for(int i=1;i<=n;i++)book[i]=i;

    int ans = 0, num = 0;

    for(int i=1;i<=m;i++)///Kruaskal
    {
        int t1 = Find(Nod[i].from);
        int t2 = Find(Nod[i].to);
        if(t1!=t2)
        {
            book[t2]=t1;///随意,book[t1]=t2;也行
            num++;
            ans += Nod[i].spend;
        }
        if(num==n-1)break;///删掉也行
    }
    printf("%d\n",ans);

    return 0;
}

猜你喜欢

转载自blog.csdn.net/du_mingm/article/details/81326168