abc259D 沿圆是否可以从S走到T
题面:二维平面上有n个圆,第i个圆的圆心在(x[i],y[i]),半径为r[i],另外给定圆上的点S和T,问从S出发沿着圆是否可以到达T?
范围:n<3E3; x[i],y[i],r[i]<1E9
思路:如果两圆相交,那么可以互相到达,枚举所有圆对,检查两两之间是否相交,用并查集维护连通关系。最后判断S和T是否属于同一个连通块即可。
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define rep(i,a,b) for(int i=a; i<=b; i++)
#define per(i,a,b) for(int i=b; i>=a; i--)
const int N = 3005;
int n, sx, sy, tx, ty, X[N], Y[N], R[N], fa[N];
int leader(int x) {
return x == fa[x] ? x : fa[x] = leader(fa[x]);
}
void join(int x, int y) {
x = leader(x);
y = leader(y);
if (x != y) {
fa[x] = y;
}
}
int distance(int x1, int y1, int x2, int y2) {
return (x1-x2)*(x1-x2) + (y1-y2)*(y1-y2);
}
void solve() {
cin >> n >> sx >> sy >> tx >> ty;
rep(i,1,n) cin >> X[i] >> Y[i] >> R[i];
rep(i,1,n) fa[i] = i;
rep(i,1,n) rep(j,i+1,n) {
int rsum = (R[i]+R[j]) * (R[i]+R[j]);
int rdif = (R[i]-R[j]) * (R[i]-R[j]);
int dist = distance(X[i],Y[i],X[j],Y[j]);
if (rdif <= dist && dist <= rsum) {
join(i, j);
}
}
set<int> st;
rep(i,1,n) {
if (distance(sx,sy,X[i],Y[i]) == R[i]*R[i]) {
st.insert(leader(i));
}
}
rep(i,1,n) {
if (distance(tx,ty,X[i],Y[i]) == R[i]*R[i]) {
if (st.count(leader(i))) {
cout << "Yes\n";
return;
}
}
}
cout << "No\n";
}
signed main() {
cin.tie(0)->sync_with_stdio(0);
int t = 1;
while (t--) solve();
return 0;
}