justoj connect(边的处理)

CONNECT

https://oj.ismdeep.com/contest/problem?id=1702&pid=2

Problem Description

有nn个顶点,每个顶点有自己的坐标(Xi,Yi,Zi)(Xi,Yi,Zi),现在想把这nn个顶点连接起来,已知连接两个顶点uu和vv的花费是MIN(|Xu−Xv|,|Yu−Yv|,|Zu−Zv|) 。现在,请花费最小的代价把这些点连接起来。

Input

第一行输入一个整数n (1≤n≤2∗105)n (1≤n≤2∗105)

接下来nn行,第ii行包含33个整数XiXi,YiYi和ZiZi(|Xi|,|Yi|,|Zi|≤109)(|Xi|,|Yi|,|Zi|≤109),代表第ii个点的坐标,数据保证不会有任意两个点的坐标相同

Output

输出最小代价

Sample Input

3
1 1 1
2 3 4
5 5 5

Sample Output

2

思路:本质是最小生成树。需要对边进行处理。

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn = 200000 + 5;

struct Edge
{
    ll u,v,dis;
};

struct Point
{
    ll x,y,z,index;
};
Edge edge[maxn*3];
Point point[maxn];

int fa[maxn];
ll edgenum;
ll res;

bool cmpx(Point a,Point b)
{
    return a.x<b.x;
}

bool cmpy(Point a,Point b)
{
    return a.y<b.y;
}

bool cmpz(Point a,Point b)
{
    return a.z<b.z;
}

bool cmpdis(Edge a,Edge b)
{
    return a.dis<b.dis;
}

int find(int x)
{
    while(x!=fa[x])
    x=fa[x]=fa[fa[x]];
    return x;
}

int main() 
{
    ll n;
    scanf("%lld",&n);
    for(int i=0;i<n;i++)
    {
        scanf("%lld%lld%lld",&point[i].x,&point[i].y,&point[i].z);
        point[i].index=i;
    }
    edgenum=0;
    sort(point,point+n,cmpx);
    for(int i=0;i<n-1;i++)
    {
        edge[edgenum].u=point[i+1].index;
        edge[edgenum].v=point[i].index;
        edge[edgenum].dis=point[i+1].x-point[i].x;
        edgenum++;
    }
    sort(point,point+n,cmpy);
    for(int i=0;i<n-1;i++)
    {
        edge[edgenum].u=point[i+1].index;
        edge[edgenum].v=point[i].index;
        edge[edgenum].dis=point[i+1].y-point[i].y;
        edgenum++;
    }
    sort(point,point+n,cmpz);
    for(int i=0;i<n-1;i++)
    {
        edge[edgenum].u=point[i+1].index;
        edge[edgenum].v=point[i].index;
        edge[edgenum].dis=point[i+1].z-point[i].z;
        edgenum++;
    }
    sort(edge,edge+edgenum,cmpdis); //把每条边从小到大排

    for(int i=0;i<n;i++)
    fa[i]=i;
    int eu,ev,cnt=0;
    for(int i=0;i<edgenum;i++)
    {
        eu=find(edge[i].u);
        ev=find(edge[i].v);
        if(eu!=ev){
        fa[ev]=eu;
        res+=edge[i].dis;
        cnt++;
        }
        if(cnt==n-1) break;
    }
    printf("%lld\n",res);
    return 0;
}
posted @ 2019-11-28 01:09  chilkings  阅读(187)  评论(0编辑  收藏  举报