题目大意:ACM公司,有n台电脑损坏了,现在可以进行两种操作,O表示修复一台电脑,S表示查询这两台电脑之间是否可以相连通,相连通的条件有两个,满足一个即可,一、这两台电脑之间距离小于等于d,二、这两台电脑可以通过其他电脑相互达到。
分析:用并查集维护可以联通的电脑,当修好一台电脑后,遍历一遍已修好的电脑,如果距离小于等于d,就加入并查集中。这样查询的时候,只要判断两台电脑是否在一个并查集即可。
代码:
#include <cstdio> #include <cmath> #include <cstring> #include <cstdlib> #include <algorithm> using namespace std; struct dot{ int x, y; }; dot a[1111]; int n, f[1111]; double d; int repaired[1111]; int Find(int k) { return f[k] == k ? k : f[k] = Find(f[k]); } void Union(int i, int j) { int pi = Find(i); int pj = Find(j); if(pi == pj) return ; else f[pi] = pj; } bool dist(int i, int j) { double dd = sqrt(1.0*(a[i].x-a[j].x)*(a[i].x-a[j].x)+1.0*(a[i].y-a[j].y)*(a[i].y-a[j].y)); if(dd <= d ) return true; else return false; } int main() { scanf("%d%lf", &n, &d); for(int i = 1; i <= n; i++) { scanf("%d%d", &a[i].x, &a[i].y); f[i] = i; } char op[2]; int p, q, cnt = 0; memset(repaired, 0, sizeof(repaired)); while(scanf("%s%d", &op, &p) != EOF) { if(op[0] == 'O') { for(int i = 0; i < cnt; i++) { //与已修好的电脑合并 if(dist(repaired[i], p)) Union(repaired[i], p); } repaired[cnt++] = p; } else { scanf("%d", &q); if(Find(p) == Find(q)) printf("SUCCESS\n"); else printf("FAIL\n"); } } return 0; }