Codeforces 333E Summer Earnings - bitset
显然答案是三点间任意两点之间的距离的最小值的一半。
那么一定有一对点的距离会被算入答案。
考虑将所有边按距离从大到小排序。当加入某一条边的时候出现了三元环。那么这条边的长度的一半就是答案。
至于判断三元环就用bitset。再加上很难跑满,以及for自带二分之一常数就过了。
标算是二分答案,然后枚举一个点,保留距离和它大于等于$mid$的所有点,求一个凸包然后判断之间最远点对的距离是否大于等于$mid$。
时间复杂度$O(n^{2}\log V)$,常数比较大,可能会比较卡,需要特殊卡常技巧。
由于答案一定与某一条边的长度有关,所以应该可以二分是哪一条边来减小常数。
Code
1 /** 2 * Codeforces 3 * Problem#333E 4 * Accepted 5 * Time: 2246ms 6 * Memory: 142056k 7 */ 8 #include <algorithm> 9 #include <iostream> 10 #include <cstdlib> 11 #include <bitset> 12 #include <cstdio> 13 #include <cmath> 14 #include <ctime> 15 using namespace std; 16 typedef bool boolean; 17 #define ll long long 18 19 typedef class Point { 20 public: 21 int x, y; 22 }Point; 23 24 ll dis2(Point a, Point b) { 25 return (a.x - b.x) * 1ll * (a.x - b.x) + (a.y - b.y) * 1ll * (a.y - b.y); 26 } 27 28 typedef class Data { 29 public: 30 int x, y; 31 ll dis; 32 33 boolean operator < (Data b) const { 34 return dis > b.dis; 35 } 36 }Data; 37 38 int n, m; 39 ll res = 0; 40 Point* ps; 41 Data* ds; 42 bitset<3005> *bs; 43 44 inline void init() { 45 scanf("%d", &n); 46 ds = new Data[(n * n + 1)]; 47 ps = new Point[(n + 1)]; 48 bs = new bitset<3005>[(n + 1)]; 49 for (int i = 1; i <= n; i++) 50 scanf("%d%d", &ps[i].x, &ps[i].y); 51 } 52 53 inline void solve() { 54 for (int i = 1; i <= n; i++) 55 for (int j = i + 1; j <= n; j++) 56 ++m, ds[m].x = i, ds[m].y = j, ds[m].dis = dis2(ps[i], ps[j]); 57 sort(ds + 1, ds + m + 1); 58 for (int i = 1; i <= m; i++) { 59 int x = ds[i].x, y = ds[i].y; 60 if ((bs[x] & bs[y]).count()) { 61 printf("%.9lf", sqrt(ds[i].dis) / 2); 62 return; 63 } 64 bs[x][y] = 1, bs[y][x] = 1; 65 } 66 puts("0"); 67 } 68 69 70 int main() { 71 init(); 72 solve(); 73 return 0; 74 }