Gym - 100625G Getting Through 计算几何+并查集
题意:平面内给你一个y轴为左边界,宽度为w的长条形区域,区域内n个半径为r的圆,问你最大能够通过这个区域的圆的半径是多少。
思路:这题和POJ 3798差不是很多,感觉像是简化版。之前鲍佳提到过那个题,谈到过并查集,不过我没写过。知道并查集这题就很好想了,在圆与圆,圆与左右边界之间都连一条边,边长就是他们的距离。那么答案就是这些边中的一条了。现在将边排好序,从小到大加到并查集里面,每加一次find一下左边界和右边界是不是连到一起了,如果连起来了,那这条边就是答案,直接输出。最后还没连起来的话,就无解了。
1 #pragma comment(linker, "/STACK:1000000000") 2 #include <iostream> 3 #include <cstdio> 4 #include <fstream> 5 #include <algorithm> 6 #include <cmath> 7 #include <deque> 8 #include <vector> 9 #include <queue> 10 #include <string> 11 #include <cstring> 12 #include <map> 13 #include <stack> 14 #include <set> 15 #define LL long long 16 #define MAXN 1005 17 #define INF 0x3f3f3f3f 18 #define eps 1e-8 19 using namespace std; 20 struct Circle 21 { 22 int x, y, r; 23 }; 24 struct Node 25 { 26 int from, to; 27 double dis; 28 Node(int from, int to, double dis):from(from), to(to), dis(dis){}; 29 }; 30 Circle a[MAXN]; 31 vector<Node> p; 32 int father[MAXN]; 33 double GetDis(int u, int v) 34 { 35 double x = abs(a[u].x - a[v].x); 36 double y = abs(a[u].y - a[v].y); 37 double r = a[u].r + a[v].r; 38 return sqrt(x * x + y * y) - r; 39 } 40 int find(int x) 41 { 42 if(x == father[x]) return x; 43 father[x] = find(father[x]); 44 return father[x]; 45 } 46 bool compare(Node a, Node b) 47 { 48 return a.dis < b.dis; 49 } 50 int main() 51 { 52 #ifndef ONLINE_JUDGE 53 freopen("in.txt", "r", stdin); 54 //freopen("out.txt", "w", stdout); 55 #endif // OPEN_FILE 56 int T; 57 scanf("%d", &T); 58 while(T--){ 59 int w; 60 scanf("%d", &w); 61 int n; 62 scanf("%d", &n); 63 if(n == 0){ 64 double ans = w; 65 ans /= 2; 66 printf("%.7lf\n", ans); 67 continue; 68 } 69 for(int i = 1; i <= n; i++){ 70 scanf("%d%d%d", &a[i].x, &a[i].y, &a[i].r); 71 } 72 for(int i = 0; i <= n + 1; i++){ 73 father[i] = i; 74 } 75 p.clear(); 76 for(int i = 1; i <= n; i++){ 77 for(int j = i + 1; j <= n; j++){ 78 p.push_back(Node(i, j, GetDis(i, j))); 79 } 80 } 81 for(int i = 1; i <= n; i++){ 82 p.push_back(Node(i, 0, a[i].x - a[i].r)); 83 p.push_back(Node(i, n + 1, w - a[i].x - a[i].r)); 84 } 85 n++; 86 sort(p.begin(), p.end(), compare); 87 int m = p.size(); 88 double ans = 0; 89 bool flag = false; 90 for(int i = 0; i < p.size(); i++){ 91 int x = find(p[i].from); 92 int y = find(p[i].to); 93 if(x == y) continue; 94 father[x] = y; 95 x = find(0); 96 y = find(n); 97 if(x == y && p[i].dis > 0){ 98 ans = p[i].dis; 99 flag = true; 100 break; 101 } 102 } 103 if(flag){ 104 printf("%.7lf\n", ans / 2); 105 } 106 else{ 107 printf("0\n"); 108 } 109 } 110 }