题目:
题目链接:
D - Circumferences (atcoder.jp)
题目思路:
题目所求为能否从一个点
通过圆边到达另外一点
因为每个圆之间有交点存在连通的可能性
我们就只需要判断两个点
1.是否都在圆上
2.所在的圆是否连通
因为涉及到连通的问题
那我们就可以使用并查集来解决问题
共同定义相交的圆存在一个共同祖先
最后判断是否是同一个祖先即可
因为要两个点是否在圆上
以及要判断两个圆是否相交
我们可以先设定如下的函数
判断起点和终点是否在圆上:
bool chekon(int tx, int ty, node t) {//检测点是否在圆边上
double tmb = sqrt(pow(tx - t.x, 2) + pow(ty - t.y, 2));
if (fabs(tmb - t.r) < 1e-7) return true;
return false;
}
判断两个圆是否相交
bool check(node A, node B) {//检查两个圆是否相交
double tmb = sqrt(pow(A.x - B.x, 2) + pow(A.y - B.y, 2));
if (tmb <= A.r + B.r && tmb >= fabs(A.r - B.r)) return true;
return false;
}
此外我们就只需要用并查集来
达到连通相交圆的目地
并查集模板
1.对标记数组进行预处理
void pre(int n) {
for (int i = 0; i <= n; i++) {
vis[i] = i;
}
}
2.find()查询找到祖宗
int find(int t) {
if (vis[t] != t) {
return vis[t] = find(vis[t]);
}
return t;
}
3.uni()更改相交两个圆中的一个圆的祖宗为另外一个
void un(int a, int b) {
if (find(a) != find(b)) {
vis[find(a)] = find(b);
}
}
继而且进行一些细节方面的处理问题就解决问题了
详细代码:
#include<stdio.h>
#include<iostream>
using namespace std;
#include<cmath>
#define int long long
#define double long double
int vis[3006];
struct node {
double x;
double y;
double r;
}arr[3006];
void pre(int n) {
for (int i = 0; i <= n; i++) {
vis[i] = i;
}
}
int find(int t) {
if (vis[t] != t) {
return vis[t] = find(vis[t]);
}
return t;
}
void un(int a, int b) {
if (find(a) != find(b)) {
vis[find(a)] = find(b);
}
}
bool check(node A, node B) {//检查两个圆是否相交
double tmb = sqrt(pow(A.x - B.x, 2) + pow(A.y - B.y, 2));
if (tmb <= A.r + B.r && tmb >= fabs(A.r - B.r)) return true;
return false;
}
bool chekon(int tx, int ty, node t) {//检测点是否在圆边上
double tmb = sqrt(pow(tx - t.x, 2) + pow(ty - t.y, 2));
if (fabs(tmb - t.r) < 1e-7) return true;
return false;
}
signed main() {
int n;
double sx, sy, tx, ty;
cin >> n;
cin >> sx >> sy >> tx >> ty;
pre(n);
int f1 = -1, f2 = -1;
for (int i = 0; i < n; i++) {
cin >> arr[i].x >> arr[i].y >> arr[i].r;
if (chekon(sx, sy, arr[i])) {
f1 = i;
}
if (chekon(tx, ty, arr[i])) {
f2 = i;
}
}
if (f1 == -1 || f2 == -1) {
cout << "No" << endl;
return 0;
}
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
if (check(arr[i], arr[j])) {
un(i, j);
}
}
}
if (find(f1) == find(f2)) cout << "Yes";
else cout << "No";
return 0;
}