题目连接
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; } } }