题意
一个计算机网络里的计算机都坏了, 现在有两种操作, “O p”代表修复了p机器, “S p q”代表检查 p, q 两台机器是否连接( 直线距离<=d或者中间有距离<=d的用来联通的机器 )
思路
比赛的时候愣是没读清楚题目意思, 还以为是什么搜索, 瞎瘠薄做了个MLE
没料到居然是个并查集, 注意应该是直线距离 <= d, 不是上下左右走的
每次修复一个机器的时候检查他与其他机器的直线距离, 并将其并入集合中
查找的时候寻找根节点就ojbk
读题没读明白是一方面, 总的来说还是做题经验不够
AC代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
const int maxn = 1e3 + 5;
int mrk[maxn];
int n, d;
char op[2];
struct computer{
int f;
int x, y;
}p[maxn];
void init(){
for( int i = 1; i <= maxn; i++ )
p[i].f = i;
return;
}
int _find( int a ){
if( a != p[a].f )
return _find(p[a].f);
return a;
}
double getdis( int x1, int y1, int x2, int y2 ){
double dx = fabs((double)(x1-x2));
double dy = fabs((double)(y1-y2));
double dis = sqrt(dx*dx+dy*dy);
return dis;
}
void _union( const computer a, const computer b ){
int aa = _find(a.f);
int bb = _find(b.f);
if( aa != bb )
if( getdis(a.x, a.y, b.x, b.y) <= d )
p[bb].f = aa;
return;
}
int main()
{
int a, b;
init();
scanf("%d%d",&n, &d);
for( int i = 1; i <= n; i++ ){
scanf("%d%d", &p[i].x, &p[i].y);
}
while( ~scanf("%s",op) ){
if( op[0] == 'O' ){
scanf("%d",&a);
mrk[a] = 1;
for(int i = 1; i <= n; i++)
if( mrk[i] && i != a)
_union(p[i], p[a]);
}
else if( op[0] == 'S' ){
scanf("%d%d",&a, &b);
if( _find(a) == _find(b) ) puts("SUCCESS");
else puts("FAIL");
}
}
return 0;
}