传送门:D - Circumferences (atcoder.jp)
题意:N个圆,两个点,判断是否能沿着这些圆的边从起点走到中点,
让我想起小时候走花台的时候(现在也走
稍微一想就能得到一个清晰的思路,两点以题目要求的方式连通需要满足以下条件:
- 两点均要在至少一个圆上;
- 能找出一条由圆构成的通路,满足路径上每个圆相交或相切
那么相应的写法就有了,我先判断每两个圆之间是否相交或相切():若是,则看作两圆相连通,否则不做处理;然后选两点中一点作为起点,深搜判断是否能走到终点即可。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N = 3e3 + 5;
int st;
bool ed[N], vis[N];
vector<int> v[N], sta;
struct node {
ll x, y, r;
}a[N];
ll getd(node p, node q){
return (p.x-q.x)*(p.x-q.x) + (p.y-q.y)*(p.y-q.y);
}
ll getp(ll a){
return a*a;
}
bool dfs(int x){
if(ed[x]){
return true;
}
if(vis[x]){
return false;
}
vis[x] = 1;
for(int i = 0;i < v[x].size(); i ++){
if(dfs(v[x][i])){
return true;
}
}
return false;
}
int main(){
int n;
cin >> n;
node s, e;
cin >> s.x >> s.y >> e.x >> e.y;
for(int i = 1; i <= n; i ++){
cin >> a[i].x >> a[i].y >> a[i].r;
// a[i].r = a[i].r * a[i].r;
if(getd(a[i], s) == a[i].r * a[i].r){
sta.push_back(i);
}
if(getd(a[i], e) == a[i].r * a[i].r){
ed[i] = 1;
}
}
for(int i = 1;i <= n; i ++){
for(int j = i + 1; j <= n; j ++){
ll tmp = getd(a[i], a[j]);
if(tmp <= getp(a[i].r+a[j].r) && tmp >= getp(a[i].r - a[j].r)){
v[i].push_back(j);
v[j].push_back(i);
}
}
}
int f = 0;
for(int i = 0;i < sta.size(); i ++){
for(int j = 1;j <= n; j++) vis[j] = 0;
if(dfs(sta[i])){
f = 1;
break;
}
}
if(f) printf("Yes\n");
else printf("No\n");
return 0;
}