这个题并不难,就是并查集的运用,下面的程序是正确的~
但是里面的红色代码部分应该可以用break来进行优化剪枝的,这样运行时间会短一些,但是不知为什么如果加上break运行结果就不对了的,如果有哪位高手知道了的话请告诉我一下哟~先谢谢喽O(∩_∩)O~
#include<iostream>
using namespace std;
const int Max = 1005;
struct data
{
int x, y, pa;
bool flag; //flag标记电脑是否修好
}com[Max];
int n, d;
void make_set() //初始化
{
for(int x = 1; x <= n; x ++)
{
com[x].pa = x;
com[x].flag = false;
}
}
int find_set(int x) //找最终根节点
{
if(x != com[x].pa)
com[x].pa = find_set(com[x].pa);
return com[x].pa;
}
void union_set(int x, int y)
{
x = find_set(x);
y = find_set(y);
if(x == y)
return;
com[y].pa = x;
}
bool dir(int x, int y) //判断两修好的电脑是不是在距离之内
{
float a = com[x].x - com[y].x;
float b = com[x].y - com[y].y;
if(a * a + b * b <= d * d)
return true;
else
return false;
}
int main(){
int x, y;
char str[10];
scanf("%d %d", &n, &d);
for(x = 1; x <= n; x ++)
scanf("%d %d", &com[x].x, &com[x].y);
getchar();
make_set(); //要记得初始化
while(scanf("%s", str) != EOF) //学习这种新的输入格式
{
if(str[0] == 'O')
{
scanf("%d", &x);
com[x].flag = true; //标记该电脑为已维修过
for(y = 1; y <= n; y ++)
if(com[y].flag && dir(x, y))
{union_set(x, y); /*break;*/} //为什么这边不能加break剪枝呢??????????
}
else
{
scanf("%d %d", &x, &y);
if(com[x].flag && com[y].flag && find_set(x) == find_set(y))
printf("SUCCESS/n");
else
printf("FAIL/n");
}
}
return 0;
}