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;
}
posted @ 2024-03-08 21:54  chenfy27  阅读(5)  评论(0编辑  收藏  举报