Time Limit: 10000MS | Memory Limit: 65536K | |
Total Submissions: 13361 | Accepted: 5659 |
Description
Input
Output
Sample Input
4 1 0 1 0 2 0 3 0 4 O 1 O 2 O 4 S 1 4 O 3 S 1 4
Sample Output
FAIL SUCCESS
Source
题意:给你 N 台坏了的电脑的坐标 ,和一个距离范围 d .
(在距离范围内的电脑可以相互通信,每台电脑也可以连接两台不同的电脑,使他们之间能够通信)
输入任意次数操作:
O x 表示修理好编号为 x 台的电脑
S x y 判断电脑 x 和 y 是否能够通信 。能则 SUCCESS ,不能则 FAIL
算法:并查集简单应用,判断两点是否在同一连通分量
思路:并查集部分很好处理。
关键是判断两台电脑是否在给定范围内,这里要用一个map[][]数组标记连通性,用一个used[]数组标记是否修理过。
每修一台电脑,则连接【合并】这台电脑和已经距离这台电脑 d 范围内的已经修好了的电脑所在的集合即可。
H | Accepted | 1164 KB | 1125 ms | C++ | 1714 B | 2013-04-10 18:48:34 |
#include<cstdio> #include<cmath> #include<cstring> const double esp = 1e-7; const int maxn = 1000+10; int p[maxn]; //父节点 bool used[maxn]; //标记改点是否修理 bool map[maxn][maxn]; //标记连通性 struct Point { double x, y; }point[maxn]; int find(int x) { return x == p[x] ? x : p[x] = find(p[x]); } void Union(int x, int y) { int fx = find(x); int fy = find(y); if(fx == fy) return; p[fx] = fy; //随意 } double dist(Point a, Point b) { return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } int main() { int n, d; while(scanf("%d%d", &n, &d) != EOF) { memset(map, false, sizeof(map)); memset(used, false, sizeof(used)); for(int i = 1; i <= n; i++) { scanf("%lf%lf", &point[i].x, &point[i].y); } for(int i = 1; i <= n; i++) { p[i] = i; map[i][i] = true; for(int j = i+1; j <= n; j++) { if(dist(point[i], point[j])-d < esp) { map[i][j] = true; //在距离范围内 map[j][i] = true; } } } char c; int x, y; getchar(); while(scanf("%c", &c) != EOF) { if(c == 'O') { scanf("%d%*c", &x); if(!used[x]) //以前未被修理 { for(int i = 1; i <= n; i++) //依次判断 { if(used[i] && map[i][x]) Union(x, i); } used[x] = true; } } else if(c == 'S') { scanf("%d%d%*c", &x, &y); if(find(x) == find(y)) printf("SUCCESS\n"); //连通 else printf("FAIL\n"); //不连通 } } } return 0; }