题目网址
题意:输入N为(坏的)电脑的数目,D是两个电脑的最大可通信距离,下面N行是N个电脑的坐标。电脑之间可以直接通信,也可以通过其他的电脑间接通信。以下有不定行输入,O后面跟着一个数字a代表修复编号为a的电脑,可以与其他的电脑通信;S后面跟着两个数字a,b,询问编号为a,b的电脑是否能通信。
所考知识点:并查集
题目解析:一开始做的时候把题想复杂了,在合并集合的时侯考虑到距离与是否修复的问题时,十分纠结。其实只要一个电脑修复,则遍历所有已修复的电脑,总能与之前的集合合并。不存在与某个根节点的距离大于给定范围,但与其父亲节点距离小于给定范围的情况无法合并的问题,因为便利了所有已修复的电脑,总能合并。
#include <iostream>
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <deque>
#include <vector>
#include <queue>
#include <string>
#include <cstring>
#include <map>
#include <stack>
#include <set>
#include <climits>
using namespace std;
const int MAXN=1e3+10;
int N;
double D, x[MAXN], y[MAXN];///横纵坐标储存数组
int parent[MAXN];
bool flag[MAXN];///标记电脑是否成功修复
int Find(int a)
{
while(a!=parent[a])
a=parent[a];
return a;
}
bool dis(int a, int b)
{
double c=x[a]-x[b];
double d=y[a]-y[b];
double e=sqrt(c*c+d*d);
if(e<=D)
return true;
else
return false;
}
void start()
{
for(int i=0; i<=N; i++)
parent[i]=i;
}
int main()
{
while(cin>>N>>D)
{
for(int i=1; i<=N; i++)
cin>>x[i]>>y[i];
start();
char x;
int m ,n;
while(cin>>x)
{
if(x=='O')
{
cin>>n;
flag[n]=true;
for(int i=1; i<=N; i++)
{
if(flag[i])
{
int a=Find(i), b=Find(n);
if(a!=b&&dis(n,i))///遍历了所有已修复的电脑,总能与已修复的电脑集合合并
parent[a]=b;
}
}
}
else if(x=='S')
{
cin>>m>>n;
{
if(flag[m]&&flag[n]&&Find(m)==Find(n))
cout<<"SUCCESS"<<endl;
else
cout<<"FAIL"<<endl;
}
}
}
}
return 0;
}