题目连接
https://vjudge.net/contest/397891#problem/B
密码:20201002
解题思路
并查集,半个板子题。
并查集讲解
区别在于,本题并非一条边一条边的join的,而是每次插入一个点,让插入的这个点和已经插入的所有距离满足条件的点join,不满足的只标记插入,但是不进行join。
对于修理电脑操作而言如上。
对于询问两台电脑是否相连,本质上是判断二者是否连通,即根是否相同且必须二者已经插入(其实只要根相同必然是插入的,可以不用判断flag,不过我没试)。
AC代码
#include<iostream>
#include<cmath>
#define ll long long
using namespace std;
const int N=1010;
ll d,n,h[N],z[N],f[N],flag[N];
char op;
int p,q;
void Init(){
for(int i=1;i<=n;i++) f[i]=i;
}
int find(int x){
return f[x]==x?x:f[x]=find(f[x]);
}
void join(int x,int y){
int rx=find(x),ry=find(y);
if(rx!=ry) f[rx]=ry;
}
double Dis(int i,int j){//求欧几里得距离函数
return sqrt((h[i]-h[j])*(h[i]-h[j])+(z[i]-z[j])*(z[i]-z[j]));
}
int main(){
cin>>n>>d;
Init();
for(int i=1;i<=n;i++) cin>>h[i]>>z[i];
while(cin>>op){
if(op=='O'){
cin>>p;
for(int i=1;i<=n;i++){
if(flag[i]==1 && i!=p && Dis(i,p)<=d) join(i,p);
}
flag[p]=1;
}
else{
cin>>p>>q;
if(find(p)==find(q) && flag[p]==1 && flag[q]==1) cout<<"SUCCESS"<<endl;
else cout<<"FAIL"<<endl;
}
}
}
京公网安备 11010502036488号