• 最小生成树


    最小生成树

    题目描述

    某个宇宙帝国有N个星球,由于宇宙的空间是三维的,因此每个星球的位置可以用三维坐标(X,Y,Z)来表示。任意两个不同的星球i和j都有一条边相连,边的距离是这样计算的:dis[i,j]=min(|Xi-Xj|,|Yi-Yj|,|Zi-Zj|),其中| | 符号表示取绝对值。现在让你来挑N-1条边,让这N个星球连通成一个最小生成树,输出构成最小生成树的N-1条边的长度总和。

    输入

    第1行,一个整数N(1≤N≤100000)。

    接下来有N行,每行三个整数X,Y,Z,表示一个星球的坐标,-1000000000≤X,Y,Z≤1000000000。没有两个星球的位置完全重叠。

    输出

    1行,构成最小生成树的N-1条边的长度总和。

    样例输入

    5
    11 -15 -15
    14  -5 -15
    -1 -1 -5
    10 -4 -1
    19 -4 19
    

    样例输出

    4
    分析:将坐标按分别按X,Y,Z轴排序后,取相邻两点坐标差为距离,利用kruskal算法即可;
    代码:
    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    #include <algorithm>
    #include <climits>
    #include <cstring>
    #include <string>
    #include <set>
    #include <map>
    #include <queue>
    #include <stack>
    #include <vector>
    #include <list>
    #include <ext/rope>
    #define rep(i,m,n) for(i=m;i<=n;i++)
    #define rsp(it,s) for(set<int>::iterator it=s.begin();it!=s.end();it++)
    #define vi vector<int>
    #define pii pair<int,int>
    #define mod 1000000007
    #define inf 0x3f3f3f3f
    #define pb push_back
    #define mp make_pair
    #define fi first
    #define se second
    #define ll long long
    #define pi acos(-1.0)
    const int maxn=3e5+10;
    const int dis[4][2]={{0,1},{-1,0},{0,-1},{1,0}};
    using namespace std;
    using namespace __gnu_cxx;
    ll gcd(ll p,ll q){return q==0?p:gcd(q,p%q);}
    ll qpow(ll p,ll q){ll f=1;while(q){if(q&1)f=f*p;p=p*p;q>>=1;}return f;}
    int n,m,p[maxn],cnt;
    ll ans;
    int merge(int x)
    {
        return p[x]==x?x:p[x]=merge(p[x]);
    }
    struct node
    {
        int x,y,l;
        bool operator<(const node&p)const
        {
            return l<p.l;
        }
    }l[maxn];
    pii a[maxn],b[maxn],c[maxn];
    int main()
    {
        int i,j,k,t;
        scanf("%d",&n);
        rep(i,1,n)p[i]=i;
        rep(i,1,n)scanf("%d%d%d",&a[i].fi,&b[i].fi,&c[i].fi),a[i].se=b[i].se=c[i].se=i;
        sort(a+1,a+n+1);
        sort(b+1,b+n+1);
        sort(c+1,c+n+1);
        j=0;
        rep(i,1,n-1)
        {
            l[j].x=a[i].se;
            l[j].y=a[i+1].se;
            l[j++].l=a[i+1].fi-a[i].fi;
    
            l[j].x=b[i].se;
            l[j].y=b[i+1].se;
            l[j++].l=b[i+1].fi-b[i].fi;
    
            l[j].x=c[i].se;
            l[j].y=c[i+1].se;
            l[j++].l=c[i+1].fi-c[i].fi;
        }
        sort(l,l+j);
        rep(i,0,j-1)
        {
            int fa=merge(l[i].x),fb=merge(l[i].y);
            if(fa!=fb)p[fa]=fb,cnt++,ans+=l[i].l;
            if(cnt==n-1)break;
        }
        printf("%lld
    ",ans);
        //system ("pause");
        return 0;
    }
     
  • 相关阅读:
    git基本操作及设置
    5-13 多页面打包配置
    笔记待整理
    单例模式在多线程下的多种实现模式
    面试题小练习1106
    求两个字符串的最大共有子串
    单例模式
    静态初始化一个二维数组并将二维数组排序并输出
    java中数组的基本知识
    关于break语句如何结束多重循环的嵌套
  • 原文地址:https://www.cnblogs.com/dyzll/p/5731588.html
Copyright © 2020-2023  润新知