[ABC181F] Silver Woods 题解

让我们修复 r r r.

假设飞机上有两个点, A A A B B B.设 d i s t ( A , B ) dist(A,B) dist(A,B)是两点 A A A B B B之间的距离,则如果 2 r ≤ d i s t ( A , B ) 2r≤dist(A,B) 2rdist(A,B),如果 2 r > d i s t ( B , A ) 2r>dist(B,A) 2r>dist(B,A),则不能.对于直线和点也是如此;让 d i s t ( A , B ) dist(A,B) dist(A,B)是线 A A A和点 B B B之间的距离,那么它可以通过 A B AB AB之间,如果 2 r ≤ d i s t ( A , B ) 2r≤dist(A,B) 2rdist(A,B),如果 2 r > d i s t ( B , A ) 2r>dist(B,A) 2r>dist(B,A),则不能.

让我们考虑一个图,其顶点是直线和指甲,其中每对顶点之间都有一条边,使得 2 r > d i s t ( x , y ) 2r>dist(x,y) 2r>dist(x,y).如果这两条线位于同一个连接的组件中,显然圆不能从 ( − 1 0 9 , 0 ) (-10^9,0) (109,0)移动到 ( 1 0 9 , 0 ) (10^9,0) (109,0).相反,如果两条线不在同一个连接的组件中,则圆可以从 ( − 1 0 9 , 0 ) (-10^9,0) (109,0)移动到 ( 1 0 9 , 0 ) (10^9,0) (109,0).(路线实际上可以通过右手法则构建.)

因此,使用直接查找每对顶点之间的距离,然后按距离的增加顺序在顶点对之间添加边的算法,时间复杂度为 O ( N 2 log ⁡ N ) O(N^2\log N) O(N2logN).

Code:


#include <bits/stdc++.h>
using namespace std;
#include<bits/stdc++.h>
#include<atcoder/dsu>
#define eb emplace_back
using namespace std;
vector<tuple<double,int,int>>qwq;
int n;
int main(){
    cin>>n;
    vector<pair<int,int>>a(n);
    for(auto&[x,y]:a)cin>>x>>y;
    const int S=n,T=n+1;
    for(int i=0;i<n;i++){
        auto [x,y]=a[i];
        qwq.eb(y+100,i,S);
        qwq.eb(100-y,i,T);
    }
    for(int i=0;i<n;i++)for(int j=i+1;j<n;j++){
        auto [x1, y1]=a[i];
        auto [x2, y2]=a[j];
        qwq.eb(hypot(x1-x2,y1-y2),i,j);
    }
    sort(qwq.begin(),qwq.end());
    atcoder::dsu uf(n+2);
    for(auto [l,i,j]:qwq){
        uf.merge(i,j);
        if(uf.same(S,T)){
            cout<<l/2<<endl;
            return 0;
        }
    }
}

提示:实际上时间复杂度可以达到 O ( N 2 ) O(N^2) O(N2),这里不亮做法了,自己想想看吧

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值