我要去看流星雨
Problem:F
Time Limit:1500ms
Memory Limit:65535K
Description
“天琴座流星雨是已知最古老的流星雨之一,拥有2700年的观测历史。”天文学博士、科普作家高爽称,最早有记录的天琴座流星雨可以追溯到公元前687年,在《春秋》中就有所记载。
这几天,天琴座流星雨又刷了一次屏:不少网友表示对这个历史悠久的流星雨十分期待。
在2020年的4月22日,天琴座流星雨如约而至。在这个古老且浪漫的流星雨面前,谁能不动心呢???这时候哈利波特和赫敏穿越到现代去美丽的林大观看这场流星雨。
这时,赫敏就问哈利波特一个难题,在这些流星雨能划分为几个区域呢?在星空中,任意相邻或坐标相同的流星引力之差不大于M,则称这两颗流星处于同一区域。可是哈利波特不会呀,只好来请教聪明的你了。
相邻的定义为:每颗流星的上、下、左、右、前、后的六个相邻位置被称为相邻。
现在让你求出这片星空的区域数量和最大的星空区域中的流星数量。
Input
第一行 n ,代表这个星空的流星数量。(n<=10000)
第二行整数 m ,代表亮度。(m<=1e9)
第三行到第 n+2 行,给定每一颗流星的坐标(x,y,z)和引力v。(0<=x,y,z,v<=1e9)
Output
一行整数 k 和 w ,代表区域数量和最大星空区域中的流星数量。
Sample Input
6
2
1 1 1 3
1 0 1 1
1 0 2 5
1 0 3 4
1 2 1 10
1 3 1 8
Sample Output
3 2
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const double PI = acos(-1.0);
int n, m, ans;
int s[10005], high[10005]; //并查集
bool flag[10];
struct star //结构体存储数据
{
int x, y, z, v;
} a[10005];
int find_set(int x) //找到父结点,压缩状态
{
if (x != s[x])
s[x] = find_set(s[x]);
return s[x];
}
void union_set(int x, int y) //合并
{
x = find_set(x);
y = find_set(y);
if (x != y)
{
s[x] = s[y]; //x并到y上
high[y] += high[x]; //将高度进行合并
high[x] = 0; //被合并的要清零
}
}
bool check(int i, int j) //根据题意进行判断两点间的关系
{
int dis = 0;
dis += abs(a[i].x - a[j].x);
dis += abs(a[i].y - a[j].y);
dis += abs(a[i].z - a[j].z);
if (dis <= 1 && abs(a[i].v - a[j].v) <= m)
return 1;
return 0;
}
int main()
{
ios::sync_with_stdio(false);
cin >> n >> m;
for (int i = 1; i <= n; i++)
{
cin >> a[i].x >> a[i].y >> a[i].z >> a[i].v;
s[i] = i; //并查集初始化
high[i] = 1; //初始化高度
}
for (int i = 1; i <= n; i++) //遍历两个点之间的关系
for (int j = 1; j <= n; j++)
{
if (i == j)
continue;
if (check(i, j)) //检查
union_set(i, j); //合并
}
int max_high = -1; //找到最大的高度
for (int i = 1; i <= n; i++)
if (s[i] == i)
{
++ans; //有多少个区域
max_high = max(high[i], max_high);
}
cout << ans << ' ' << max_high << endl;
return 0;
}