P4149 [IOI2011]Race

P4149 [IOI2011]Race

淀粉质点分治

处理书上路径,非常套路

(dsu on tree写挂了改不过来....)

#include<cstdio>
#include<cstring>
inline int Min(int a,int b){return a<b?a:b;}
inline int Max(int a,int b){return a>b?a:b;}
void read(int &x){
    char c=getchar();x=0;
    while(c<'0'||c>'9') c=getchar();
    while('0'<=c&&c<='9') x=x*10+c-48,c=getchar();
}
#define N 200005
int n,k,dis[N],d[N],siz[N],mx[N],rt,sum;
int D[1000005],tp,S[N],cc,q[N],ans=1e9;
bool vis[N];
int cnt,hd[N],nxt[N<<1],ed[N],poi[N<<1],val[N<<1];
inline void adde(int x,int y,int v){
    nxt[ed[x]]=++cnt, hd[x]=hd[x]?hd[x]:cnt,
    ed[x]=cnt, poi[cnt]=y, val[cnt]=v;
}
#define to poi[i]
#define Edge for(int i=hd[x];i;i=nxt[i])
void grt(int x,int fa){
    siz[x]=1; mx[x]=0;//记得清零mx数组!
    Edge if(!vis[to]&&to!=fa){
        grt(to,x); siz[x]+=siz[to];
        mx[x]=Max(mx[x],siz[to]);
    }mx[x]=Max(mx[x],sum-siz[x]);
    if(mx[x]<mx[rt]) rt=x;
}
void gdis(int x,int fa){
    S[++tp]=x; d[x]=d[fa]+1;
    Edge if(!vis[to]&&to!=fa) dis[to]=dis[x]+val[i],gdis(to,x);
}
void calc(int x){
    cc=0; D[0]=d[x]=0;
    Edge if(!vis[to]){
        tp=0; dis[to]=val[i]; gdis(to,x);
        for(int j=1;j<=tp;++j)
            if(dis[S[j]]<=k) ans=Min(ans,D[k-dis[S[j]]]+d[S[j]]);
        for(int j=1;j<=tp;++j) if(dis[S[j]]<=k){
            D[dis[S[j]]]=Min(D[dis[S[j]]],d[S[j]]);
            q[++cc]=dis[S[j]];
        }
    }
    for(int i=1;i<=cc;++i) D[q[i]]=1e9;
}
void solve(int x){
    vis[x]=1; calc(x);
    Edge if(!vis[to]) rt=0,sum=siz[to],grt(to,x),solve(rt);
}
int main(){
    memset(D,63,sizeof(D));
    read(n);read(k);
    for(int i=1,U,V,W;i<n;++i)
        read(U),read(V),read(W),adde(U+1,V+1,W),adde(V+1,U+1,W);
    mx[rt=0]=1e9; sum=n; grt(1,0); solve(rt);
    if(ans>=n) ans=-1;
    printf("%d",ans);
    return 0;
}

 

posted @ 2019-06-04 22:25  kafuuchino  阅读(244)  评论(0编辑  收藏  举报