并查集,又一个acm的重点,对于分群具有特别好的效果
思路:这一题的关键就是读题,确实题意有点晦涩,需要研究一番。
乍一看题目有点像最短路问题,仔细研究发现,给定了坐标,给定了最长距离并且传输过程可以由中间点中转,那么这一题就相当于将距离小于给定长度的点分于一个集体,内部相互可达,于是,并查集的思路瞬间开朗。
/*
Author:Owen_Q
*/
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1010;
int x[maxn],y[maxn];
int pre[maxn];
bool repair[maxn];
bool getdis(int a,int b,int d)
{
int dis = (x[a] - x[b])*(x[a] - x[b]) + (y[a] - y[b])*(y[a] - y[b]);
if(d>=dis)
{
return true;
}
else
{
return false;
}
}
int finds(int x)
{ //寻找
int r = x;
while(pre[r]!=r)
{
r = pre[r];
}
int i=x ,j;
while(pre[i]!=r)
{ //路径压缩
j = pre[i];
pre[i] = r;
i = j;
}
return r;
}
void join(int x,int y)
{ //将两个集合合并
int fx = finds(x);
int fy = finds(y);
if(fx > fy)
{
int temp = fx;
fx = fy;
fy = temp;
}
if(fx!=fy)
{
pre[fy] = fx;
}
}
vector <int> re;
int main()
{
int n,d;
scanf("%d%d",&n,&d);
d = d * d;
re.clear();
for(int i=1;i<=n;i++)
{
pre[i] = i;
scanf("%d%d",&x[i],&y[i]);
repair[i]=false;
}
char temp[5];
while(scanf("%s",temp)!=EOF)
{
if(strcmp(temp,"O")==0)
{
int computer;
scanf("%d",&computer);
vector <int> :: iterator it = re.begin();
for(;it!=re.end();it++)
{
if(getdis(computer,(*it),d))
{
join(computer,(*it));
}
}
re.push_back(computer);
repair[computer] = true;
}
else
{
int p,q;
scanf("%d%d",&p,&q);
if(repair[p]&&repair[q]&&finds(p)==finds(q))
{
printf("SUCCESS\n");
}
else
{
printf("FAIL\n");
}
}
}
return 0;
}