题意
余震过后所有电脑都坏了,给定每一个电脑的坐标,然后给你一些操作(修复和查询),对于每一个查询输出一次这两台电脑是否能通讯
思路
在裸并查集的基础上多加个判断条件就行 ,判断每一台修复的电脑与其他电脑是否可以连接。如果该电脑被修复且与某一台已修复电脑之间的距离小于 d 则这两台电脑就可以通讯。
能通讯的条件
两台电脑都被修复且距离小于 d 。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
int pre[1005],vis[1005],rank[1005];
double d;
struct node
{
int x,y;
}p[30005];
int dis(int i,int j)
{
double a=sqrt(1.0*(p[i].x-p[j].x)*(p[i].x-p[j].x)+1.0*(p[i].y-p[j].y)*(p[i].y-p[j].y));
if(a>d)
return 0;
else
return 1;
}
int find(int x)
{
int r=x;
while(r!=pre[r])
r=pre[r];
int i=x,j;
while(i!=r)
{
j=pre[i];
pre[i]=r;
i=j;
}
return r;
}
void join(int x,int y)
{
x=find(x),y=find(y);
if(x!=y)
{
if(rank[x]>rank[y])
pre[y]=x;
else
{
pre[x]=y;
if(rank[x]==rank[y])
rank[y]++;
}
}
}
int main()
{
int t;
scanf("%d%lf",&t,&d);
for(int i=1;i<=t;i++)
{
pre[i]=i;
rank[i]=1;
}
for(int i=1;i<=t;i++)
{
scanf("%d%d",&p[i].x,&p[i].y);
}
char s;
int n,m;
memset(vis,0,sizeof(vis));
getchar();
while(~scanf("%c",&s)) //注意处理换行符
{
if(s=='O')
{
scanf("%d",&n);
vis[n]=1;
for(int i=1;i<=t;i++)
{
if(vis[i]==1&&dis(i,n))
join(n,i);
}
}
else
{
scanf("%d%d",&n,&m);
if(vis[n]==1&&vis[m]==1&&find(n)==find(m)) //只有两台电脑都被修复从才有可能通讯
printf("SUCCESS\n");
else
printf("FAIL\n");
}
getchar();
}
return 0;
}