2018年江西理工大学C语言程序设计竞赛 F
31世纪,人类世界的科技已经发展到了空前的高度,星际移民,星际旅游早已经不再是问题。人类已经掌握了开发星系的能力。但是,无论发展到何种地步,资源一直是人们关注的重点。一种新的能源被人类掌握,通过它可以搭建虫洞,实现超光年传输。发展武器。但是虽然这种物质在宇宙海量的存在着,但它对于宇宙的稳定是至关重要的,若过量消耗这种物质,对于宇宙的稳定,星系与星系之间以及星系内部的微妙平衡都会产生巨大的影响。这种物质就是暗物质。
宇宙百科》节选
现在,你所在的星系下有n个主星球居住着人民。为了星系内部的稳定与和平发展,现在需要在n个主星球之间建立空间虫洞,众所周知建立虫洞要消耗大量的暗物质,因此,你想要在n个主星球之间建立联系的情况下尽量少的消耗暗物质。目前你已经知道的是,建立虫洞所需要消耗的暗物质与两个星球之间的距离成正比,比例系数为k。并且,两个星球之间的距离为空间缩点距离。每个星球有它自己的三维物理坐标。不过,现在有一个好消息。你所在的星系掌握了一项新的技术,空间奇点压缩,简单来说就是降维,但是由于技术发展初期不够成熟,只能压缩一维。并且,任意两个主星球之间都可以选择是否进行空间奇点压缩。现在,你想知道,在这n个主星球之间建立连接需要花费的最少暗物质是多少。 空间缩点距离:设两个n维坐标a(x1,x2,x3,xn),b(y1,y2,y3,y4,yn).设距离为s,则s=abs((x1+x2+x3+…+xn)−(y1+y2+y3+…+yn));
以上内容纯属瞎扯,请忽略其真实性
输入
第一行两个整数n和k。(1≤n≤105,1≤k≤103)
接下开n行,每行三个整数x,y,z,其中第i行表示第i个星球在星系中的物理坐标。数据保证没有两个星球处于同一个位置上。(1≤x,y,z≤106)
输出
n个主星球之间建立连接需要花费的最少暗物质。
样例输入
3 2
1 1 6
1 2 9
3 20 8
样例输出
4
提示
样例说明:
星球1和星球2之间压缩第三维
星球2和星球3之间压缩第二维
#include
using namespace std;
const int N = 1e5 + 10;
typedef long long ll;
int fa[N];
int n, k;
struct node{
ll x, y, z;
int id;
}a[N];
struct f{
int u, v;
ll dis;
bool operator<(const f &a) const{ //从大到小
return a.dis > dis;
}
} e[N*4];
int find(int x) //并查集
{
return fa[x] = (fa[x] == x ? x : find(fa[x]));
}
bool cmp_xyz(node a, node b) //自定义排序
{
return a.x + a.y + a.z < b.x + b.y + b.z;
}
bool cmp_xy(node a, node b)
{
return a.x + a.y < b.x + b.y;
}
bool cmp_yz(node a, node b)
{
return a.y + a.z < b.y + b.z;
}
bool cmp_xz(node a, node b)
{
return a.x + a.z < b.x + b.z;
}
void init() //把三维的和三种二维的都放入e数组,也即所有可能,
{ //等下直接对e数组Kruskal
for (int i = 1; i <= n; i++){
fa[i] = i;
}
int ans = 0;
sort(a, a + n, cmp_xyz);
for(int i = 1; i < n; i++){
e[ans++] = (f){a[i].id, a[i - 1].id, a[i].x + a[i].y + a[i].z - a[i - 1].x - a[i - 1].y - a[i - 1].z};
}
sort(a, a + n, cmp_xy);
for(int i = 1; i < n; i++){
e[ans++] = (f){a[i].id, a[i - 1].id, a[i].x + a[i].y - a[i - 1].x - a[i - 1].y};
}
sort(a, a + n, cmp_yz);
for(int i = 1; i < n; i++){
e[ans++] = (f){a[i].id, a[i - 1].id, a[i].y + a[i].z - a[i - 1].y - a[i - 1].z};
}
sort(a, a + n, cmp_xz);
for(int i = 1; i < n; i++){
e[ans++] = (f){a[i].id, a[i - 1].id, a[i].x + a[i].z - a[i - 1].x - a[i - 1].z};
}
int pos = n - 1;
sort(e, e + ans);
}
void kruskal()
{
ll res = 0;
ll ans = 4 * n;
int pos = n - 1;
for(int i = 0; i < ans && pos > 0; i++){
int x = find(e[i].u);
int y = find(e[i].v);
if(x != y){
res += e[i].dis;
fa[x] = y;
pos--;
}
}
printf("%lld\n", res * k);
}
int main()
{
scanf("%d%d", &n, &k);
for (int i = 0; i < n; i++){
scanf("%lld%lld%lld", &a[i].x, &a[i].y, &a[i].z);
a[i].id = i + 1;
}
init();
kruskal();
return 0;
}