AtCoder Beginner Contest 181 -F - Silver Woods(幾何,並查集)
阿新 • • 發佈:2020-11-20
AtCoder Beginner Contest 181 -F - Silver Woods(幾何,並查集)
題面:
題意:
在一個二維平面中,有直線\(y=100,y=-100\)兩條直線和\(\mathit n\)個釘子,座標為\((x_i,y_i)\),現在要使一個圓從平面的最左側移動到最右側,要求圓一直在兩個直線夾著的區域,且不可以包含釘子(釘子大小可以忽略不記,即可以在圓的邊框上),不能躍出直線。問你圓的半徑最大是多少?
思路:
我們可以考慮二分答案值\(\mathit r\),然後去判斷當前的數值是否滿足條件,以此來調整答案的區間。
對於當前的半徑值\(\mathit r\),對於任意兩點以及點和上下界組成的點對,點線對,若距離為\(dis\)
也可以直接建立全部的邊,按照距離升序來排序,一直加邊到上屆線和下界線連通時,該邊為最大圓的直徑。
程式碼:
#include <iostream> #include <cstdio> #include <algorithm> #include <bits/stdc++.h> #define ALL(x) (x).begin(), (x).end() #define sz(a) int(a.size()) #define rep(i,x,n) for(int i=x;i<n;i++) #define repd(i,x,n) for(int i=x;i<=n;i++) #define pii pair<int,int> #define pll pair<long long ,long long> #define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0) #define MS0(X) memset((X), 0, sizeof((X))) #define MSC0(X) memset((X), '\0', sizeof((X))) #define pb push_back #define mp make_pair #define fi first #define se second #define eps 1e-6 #define chu(x) if(DEBUG_Switch) cout<<"["<<#x<<" "<<(x)<<"]"<<endl #define du3(a,b,c) scanf("%d %d %d",&(a),&(b),&(c)) #define du2(a,b) scanf("%d %d",&(a),&(b)) #define du1(a) scanf("%d",&(a)); using namespace std; typedef long long ll; ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;} ll lcm(ll a, ll b) {return a / gcd(a, b) * b;} ll powmod(ll a, ll b, ll MOD) { if (a == 0ll) {return 0ll;} a %= MOD; ll ans = 1; while (b) {if (b & 1) {ans = ans * a % MOD;} a = a * a % MOD; b >>= 1;} return ans;} ll poww(ll a, ll b) { if (a == 0ll) {return 0ll;} ll ans = 1; while (b) {if (b & 1) {ans = ans * a ;} a = a * a ; b >>= 1;} return ans;} void Pv(const vector<int> &V) {int Len = sz(V); for (int i = 0; i < Len; ++i) {printf("%d", V[i] ); if (i != Len - 1) {printf(" ");} else {printf("\n");}}} void Pvl(const vector<ll> &V) {int Len = sz(V); for (int i = 0; i < Len; ++i) {printf("%lld", V[i] ); if (i != Len - 1) {printf(" ");} else {printf("\n");}}} inline long long readll() {long long tmp = 0, fh = 1; char c = getchar(); while (c < '0' || c > '9') {if (c == '-') { fh = -1; } c = getchar();} while (c >= '0' && c <= '9') { tmp = tmp * 10 + c - 48, c = getchar(); } return tmp * fh;} inline int readint() {int tmp = 0, fh = 1; char c = getchar(); while (c < '0' || c > '9') {if (c == '-') { fh = -1; } c = getchar();} while (c >= '0' && c <= '9') { tmp = tmp * 10 + c - 48, c = getchar(); } return tmp * fh;} void pvarr_int(int *arr, int n, int strat = 1) {if (strat == 0) {n--;} repd(i, strat, n) {printf("%d%c", arr[i], i == n ? '\n' : ' ');}} void pvarr_LL(ll *arr, int n, int strat = 1) {if (strat == 0) {n--;} repd(i, strat, n) {printf("%lld%c", arr[i], i == n ? '\n' : ' ');}} const int maxn = 1000010; const int inf = 0x3f3f3f3f; /*** TEMPLATE CODE * * STARTS HERE ***/ #define DEBUG_Switch 0 int n; pii b[maxn]; struct node { double val; int x, y; node() { } node(double _v, int _x, int _y) { val = _v; x = _x; y = _y; } bool operator<(const node &b) const { return val < b.val; } }; std::vector<node> v; double dis(pii aa, pii bb) { return sqrt((aa.fi - bb.fi) * (aa.fi - bb.fi) + (aa.se - bb.se) * (aa.se - bb.se)); } int far[maxn]; int dsu_sz[maxn]; void dsu_init(int n) { repd(i, 0, n) { far[i] = i; dsu_sz[i] = 1; } } int findpar(int x) { if (x == far[x]) { return x; } else { return far[x] = findpar(far[x]); } } void mg(int x, int y) { x = findpar(x); y = findpar(y); if (x == y) { return; } if (dsu_sz[x] > dsu_sz[y]) { dsu_sz[x] += dsu_sz[y]; far[y] = x; } else { dsu_sz[y] += dsu_sz[x]; far[x] = y; } } int S, T; void solve() { for (auto e : v) { mg(e.x, e.y); if (findpar(S) == findpar(T)) { printf("%.6f\n", e.val/2 ); return ; } } } int main() { #if DEBUG_Switch freopen("D:\\code\\input.txt", "r", stdin); #endif //freopen("D:\\code\\output.txt","w",stdout); n = readint(); S = n + 1; T = n + 2; repd(i, 1, n) { b[i].fi = readint() + 100; b[i].se = readint(); v.pb(node(100 - b[i].se, S, i)); v.pb(node(b[i].se + 100, T, i)); } repd(i, 1, n) { repd(j, i + 1, n) { v.pb(node(dis(b[i], b[j]), j, i)); } } sort(ALL(v)); dsu_init(n + 2); solve(); return 0; }