题目:https://vjudge.net/problem/POJ-2236
题目大意
地震了有n个电脑要修,两个电脑要连接距离不能超过d。如果AB要连接有两种情况,A直接连接B, AB不能直接连接但是A连接C,B连接C。给你两种操作,O意味着修复S意味着测试能否连接
分析
很明显是一个并查集题,模版加上一些限制就能过。
代码
#include <cstdio>
#include <iostream>
#include <string.h>
#include <cmath>
#include <cstdlib>
using namespace std;
#define NUM 1001
int pre[NUM];
int pos[NUM][NUM];
bool conn[NUM];
float dis[NUM];
int n, d;
int find_(int x){
int t = x;
while(t != pre[t]){
t = pre[t];
}
int k = x;
while(k != t){
int s = pre[k];
pre[k] = t;
k = s;
}
return t;
}
bool join_(int x, int y){
int xx = find_(x);
int yy = find_(y);
if(xx != yy){
pre[yy] = xx;
return false;
}
return true;
}
void op_0(int p){
conn[p] = true;
for(int i = 1; i <= n; i++){
if(conn[i] && conn[p]){
int &x1 = pos[i][0];
int &y1 = pos[i][1];
int &x2 = pos[p][0];
int &y2 = pos[p][1];
int dx = abs(x1 - x2);
int dy = abs(y1 - y2);
float dd;
dd = sqrt(dx * dx + dy * dy);
if(dd <= d){
join_(i, p);
}
}
}
}
bool op_S(int p, int q){
int pp = find_(p);
int qq = find_(q);
if(pp == qq){
return true;
}
else{
return false;
}
}
int main(){
// freopen("B.txt", "r", stdin);
scanf("%d%d", &n, &d);
for(int i = 0; i <= n; i++){
pre[i] = i;
}
memset(conn, false, sizeof(conn));
for(int i = 1; i <= n; i++){
int a, b;
scanf("%d%d", &a, &b);
pos[i][0] = a;
pos[i][1] = b;
}
char s;
while(cin >> s){
if(s == 'O'){
int p;
scanf("%d", &p);
op_0(p);
}
else if(s == 'S'){
int pp, q;
scanf("%d%d", &pp, &q);
if(op_S(pp, q)){
printf("SUCCESS\n");
}
else{
printf("FAIL\n");
}
}
}
return 0;
}