luogu P4654 [CEOI2017]マウストラップ

ポータル

ここでルートがその後の処理を容易にするために、エンド、ターゲットはマウスがルートを行ってきましたようにすることです

最初のパスのブランチブロックの終わりまで、この時点からできるこの場合には、マウスを移動することができない場合を考慮して、パス上の歩道をクリアし、あなたがこの場合の最高意思決定である見つけることができます。この場合には、マウスがある程度の距離を行くのは最初でなければならない(あるいは行かないかもしれません)、その後、サブ木の枝に入り、その後、フィニッシュラインに運ばれました。

答えはいくつかの手順を費やしなりの戦略がある場合は、マウスの場合。二分法を満たして明らかである(>中旬\)\その後、\(中旬\)は違法ではありません。だから、スタートから\(\スタート)地点にそれぞれ、上がりますこの条件を満たすために何のブランチが存在しない場合ので、それがサブツリーを入力した後、いくつかの手順を取る知っている。見て、表記\(F_Xが\) 最初にすべての必要があり、それを転送(F \)\長男がブロックされ、その後、マウスを取ります二次マウスをライン上に捕捉されたときに息子がブロックされたままの息子、これに\(F_X = |の息子\ \ X | - [| \ Xの息子\ |> 1] + F_ {X2} (\ X = \ {X1、X2、... \}、F_ {X1}>} F_ {X2> X3のF_ {...}の子\)+。1 \)

あなたは、ツリーのサブブランチを入力すると、現在のポイントのために、最初、他の枝がブロックされなければならない、そのようにその後、枝の数に注意し、祖先の枝もブロックされとる\(s_x = \ sum_ {Yの \は\祖先を\さを[Y =スタート!] \) - | \ Yの子\ | \ X、Y \ NEQルート}の\操作ステップ数の終了後に、ポイントに\(g_x = F_X + S_ { fa_x} -1 \) があれば、特定のポイントに来て\(g_x>中旬\)操作の息子の数、我々は、使用可能なブロックを消費しようとする必要があり、この数は、初期に使用することができます\(1 \)それぞれに、上のポイントに行く\(+ 1 \)などがある場合。\(g_xが\)まで行く前に、それぞれの時間が必要があることに注意することは違法ではありません(中旬\)を\現在のレイヤーをオフに使用してマイナス操作の数

// luogu-judger-enable-o2
#include <bits/stdc++.h>
#define LL long long

using namespace std;
const int N=1e6+10;
LL rd()
{
    LL x=0,w=1;char ch=0;
    while(ch<'0'||ch>'9') {if(ch=='-') w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
    return x*w;
}
int to[N<<1],nt[N<<1],hd[N],tot=1;
void add(int x,int y)
{
    ++tot,to[tot]=y,nt[tot]=hd[x],hd[x]=tot;
    ++tot,to[tot]=x,nt[tot]=hd[y],hd[y]=tot;
}
int n,rt,fa[N],sz[N],f[N],g[N],ans;
int st[N],tp;
void dfs(int x)
{
    for(int i=hd[x];i;i=nt[i])
    {
        int y=to[i];
        if(y==fa[x]) continue;
        fa[y]=x,dfs(y);
    }
    tp=0;
    for(int i=hd[x];i;i=nt[i])
    {
        int y=to[i];
        if(y==fa[x]) continue;
        st[++tp]=f[y];
    }
    sz[x]=tp;
    sort(st+1,st+tp+1);
    f[x]+=tp-(tp>1)+st[tp-1]+1;
}
bool ck(int mid,int xx)
{
    int cn=1,la=0,dt=0;
    while(xx!=rt)
    {
        st[tp=0]=sz[fa[xx]];
        for(int i=hd[xx];i;i=nt[i])
        {
            int y=to[i];
            if(y==fa[xx]||y==la) continue;
            st[++tp]=g[y];
        }
        st[0]+=tp;
        sort(st+1,st+tp+1);
        while(tp>0&&cn>0&&st[tp]>mid) --tp,--cn,++dt;
        if(st[tp]>mid) return 0;
        mid-=dt,dt=0,la=xx,xx=fa[xx],++cn;
    }
    return 1;
}

int main()
{
    n=rd(),rt=rd();
    int x=rd(),la=0;
    for(int i=1;i<n;++i) add(rd(),rd());
    dfs(rt);
    tp=0;
    int xx=x;
    while(xx!=rt) st[++tp]=xx,xx=fa[xx];
    --sz[st[tp]];
    for(int i=tp-1;i;--i) sz[st[i]]+=sz[st[i+1]]-1;
    ++sz[st[1]];
    sz[rt]=0;
    xx=x;
    while(xx!=rt)
    {
        for(int i=hd[xx];i;i=nt[i])
        {
            int y=to[i];
            if(y==fa[xx]||y==la) continue;
            g[y]=f[y]+sz[xx]-1;
        }
        la=xx,xx=fa[xx];
    }
    int l=0,r=n;
    while(l<=r)
    {
        int mid=(l+r)>>1;
        if(ck(mid,x)) ans=mid,r=mid-1;
        else l=mid+1;
    }
    printf("%d\n",ans);
    return 0;
}

おすすめ

転載: www.cnblogs.com/smyjr/p/11110880.html