Loading

NOIP 模拟 $80\; \rm 滑稽树下你和我$

题解 \(by\;zj\varphi\)

口胡一下:

采取最优策率,使得存在一种移动到叶子节点的路径最大距离最小。

二分答案,每次 \(bfs\) 看能否找到一条路径,每次找最短的,使得两个人都能到叶子节点。

有一些很神奇的技巧,看代码。

Code
#include<bits/stdc++.h>
#define ri signed
#define pd(i) ++i
#define bq(i) --i
#define func(x) std::function<x>
namespace IO{
    char buf[1<<21],*p1=buf,*p2=buf;
    #define gc() p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?(-1):*p1++
    #define debug1(x) std::cerr << #x"=" << x << ' '
    #define debug2(x) std::cerr << #x"=" << x << std::endl
    #define Debug(x) assert(x)
    struct nanfeng_stream{
        template<typename T>inline nanfeng_stream &operator>>(T &x) {
            bool f=false;x=0;char ch=gc();
            while(!isdigit(ch)) f|=ch=='-',ch=gc();
            while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=gc();
            return x=f?-x:x,*this;
        }
    }cin;
}
using IO::cin;
namespace nanfeng{
    #define fi first
    #define se second
    #define mk std::make_pair
    #define FI FILE *IN
    #define FO FILE *OUT
    template<typename T>inline T cmax(T x,T y) {return x>y?x:y;}
    template<typename T>inline T cmin(T x,T y) {return x>y?y:x;}
    using db=double;
    using ll=long long;
    static const int N=1e3+7;
    static const db eps=1e-8;
    int first[N],deg[N],vis[N][N],U[N],V[N],t=2,n,stx,sty,tim;
    struct edge{int v,nxt;}e[N<<1];
    auto add=[](int u,int v) {
        e[t]={v,first[u]},first[u]=t++;
        e[t]={u,first[v]},first[v]=t++;
        ++deg[u],++deg[v];
    };
    ll X[N],Y[N];
    auto Get=[](int x,int y) {return sqrt(1.0*(X[x]-X[y])*(X[x]-X[y])+1.0*(Y[x]-Y[y])*(Y[x]-Y[y]));};
    auto Getdis(int x,int y,int z) {
        if ((X[x]-X[y])*(X[z]-X[y])+(Y[x]-Y[y])*(Y[z]-Y[y])>0&&(X[x]-X[z])*(X[y]-X[z])+(Y[x]-Y[z])*(Y[y]-Y[z])>0) 
            return std::abs((X[y]-X[x])*(Y[z]-Y[x])-(Y[y]-Y[x])*(X[z]-X[x]))/Get(y,z);
        return cmin(Get(x,y),Get(x,z));
    };
    inline int main() {
        FI=freopen("tree.in","r",stdin);
        FO=freopen("tree.out","w",stdout);
        cin >> n >> stx >> sty;
        for (ri i(1);i<=n;pd(i)) cin >> X[i] >> Y[i];
        for (ri i(1);i<n;pd(i)) cin >> U[i] >> V[i],add(U[i],V[i]);
        db l=Get(stx,sty),r=1.5e6,res;
        auto check=[&](db lim) {
            ++tim;
            std::queue<std::pair<int,int>> que;
            auto add=[&](int x,int y) {if (vis[x][y]^tim&&Getdis(x,U[y],V[y])<=lim) vis[x][y]=tim,que.push(mk(x,y));};
            for (ri i(first[stx]);i;i=e[i].nxt) add(sty,i>>1);
            for (ri i(first[sty]);i;i=e[i].nxt) add(stx,i>>1);
            while(!que.empty()) {
                int x=que.front().fi,y=que.front().se;
                que.pop();
                if (deg[x]==1&&deg[U[y]]==1&&Get(x,U[y])<=lim) return true;
                if (deg[x]==1&&deg[V[y]]==1&&Get(x,V[y])<=lim) return true;
                for (ri i(first[x]);i;i=e[i].nxt)
                    add(e[i].v,y),add(U[y],i>>1),add(V[y],i>>1);
            }
            return false;
        };
        while(r-l>eps) {
            db mid=(l+r)/2;
            if (check(mid)) res=mid,r=mid;
            else l=mid;
        }
        printf("%.8lf\n",res);
        return 0;
    }
}
int main() {return nanfeng::main();}
posted @ 2021-10-20 08:30  ナンカエデ  阅读(39)  评论(0编辑  收藏  举报