题意就不解释了;
这道题目怎么用并查集做呢?举个例子,若a,b之间的距离小于d,说明a,b可以通信,用并查集把它们俩连在一起,这时候,倘若,a,c之间的距离也小于d,a,c之间就可以通信,那么b,c也可以通信,用并查集把a,c连在一起,此时,a,b,c连在一棵树上,表明了它们之间互相可以通信(直接或间接);同理,不在同一棵树上的点不能实现通信;
下面这段话写给自己看的 = = :
刚开始,我想到的是用最小生成树来做,后来想想,还是对最小生成树的那个dis数组理解不到位!很容易举出反例:比如a,b之间的距离大于d,a,c之间的距离大于d,b,c之间的距离小于d,那么跑完最小生成树之后,dis[c]的值应该是b到c的距离,小于d,貌似可以通信,但显然是不可以的
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
using namespace std;
int p[1009];
int find(int x)//递归+压缩路径
{
return p[x] == x ? x : p[x] = find(p[x]);
}
int n,d;
bool vis[1009];//用来标记哪些电脑修好了
int data[1009][2];//保存坐标值
void Init()//初始化
{
int i;
memset(vis,false,sizeof(vis));//刚开始所有的电脑都没有修好
for (i = 1; i <= n; ++i)
p[i] = i;
}
bool dis(int a[],int b[])//求两点之间的距离,若距离小于d,则返回true,否则返回false
{
int x = (a[0] - b[0]) * (a[0] - b[0]);
int y = (a[1] - b[1]) * (a[1] - b[1]);
if ((x+y) <= d*d)
return true;
return false;
}
int main()
{
int i,j;
char ch;
while (~scanf("%d%d",&n,&d))
{
for (i = 1; i <= n; ++i)
scanf("%d%d",&data[i][0],&data[i][1]);
Init();
while (cin>>ch)//用cin输入,这样就可以免去换行带来的不便
{
if (ch == 'O')
{
cin>>i;
vis[i] = true;
for (j = 1; j <= n; ++j)
{
if (vis[j] && dis(data[i],data[j]))//在已经修好的电脑里面,把距离小于d的连在同一棵树上
{
int x = find(i);
int y = find(j);
if (x > y) p[x] = y;
else if (x < y) p[y] = x;
}
}
}
else if (ch == 'S')
{
cin>>i>>j;
int a = find(i);
int b = find(j);
if (a == b)//如果要通信的这两点属于同一棵树,那么就可以实现通信
printf("SUCCESS\n");
else
printf("FAIL\n");
}
}
}
return 0;
}