今日无事更新一下博客
**今天写的是一道noip提高组的题目
是2017年提高组的Day2 T1
通常第一题不是很难,这题也是
传送门:点我点我
题目的意思很简单,就是让我们找一条路径
可以从z=0面到达z=h这个面
很简单的想到并查集,即 两个球之间的距离 <= 2*R 就放到同一个集合里去
并且在一个集合里同时找到了 与z=0存在通路的球 和 与z=h存在通路的球,就说明这个集合可以连通面z=0和面z=h
代码解释看注释叭
#include <cstdio>
#include <iostream>
using namespace std;
struct node
{
int x, y, z;
} hole[1010];//储存洞的坐标
int fa[1010];//储存并查集
int n, h;
int f1[1010], f2[1010];//储存与两个面连通的点
long long r;
int find(int x)
{
if (fa[x] != x)
fa[x] = find(fa[x]);//路径压缩,更新父节点
return fa[x];
}
int main()
{
int T;
scanf("%d", &T);
while (T--)
{
scanf("%d%d%lld", &n, &h, &r);
int tot1 = 0, tot2 = 0;
for (int i = 1; i <= n; i++)
fa[i] = i;//初始化,所有点的父节点都是自己
for (int i = 1; i <= n; i++)
{
scanf("%d%d%d", &hole[i].x, &hole[i].y, &hole[i].z);
if (hole[i].z <= r)//与面z=0连通的球
tot1++, f1[tot1] = i;
if (hole[i].z >= h - r)//与面z=h连通的球
tot2++, f2[tot2] = i;
for (int j = 1; j <= i; j++)
{
long long dx = hole[i].x - hole[j].x;//这三个点
long long dy = hole[i].y - hole[j].y;//必须要
long long dz = hole[i].z - hole[j].z;//用long long 存
if ((dx * dx + dy * dy + dz * dz) <= 4 * r * r)//两个球连通
{
int a1 = find(i);//找i的父节点
int a2 = find(j);//找j的父节点
fa[a1] = a2;//把两个的父节点变成同一个(加入一个集合)
}
}
}
bool s = 0;
for (int i = 1; i <= tot1 && s == 0; i++)//枚举与面z=0连通的球
for (int j = 1; j <= tot2 && s == 0; j++)//枚举与面z=h连通的球
if (find(f1[i]) == find(f2[j]))//如果两个点在同一个集合
s = 1;//找到了通路!!!!
if (s)
printf("Yes\n");
else
printf("No\n");
}
return 0;
}