bzoj1316 树上的询问(点分治)

询问m个长度的路径是否存在。
我们点分治,每次一个子树子树的做,拿一个数组记一下存在的长度,然后拿当前子树的长度去查询是否存在。因为长度只有1e6,所以可以直接拿一个bool数组去记。复杂度 O(nlognm)
如果长度1e9的话,就需要set/hash表来支持了吧qaq

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define N 10010
inline char gc(){
    static char buf[1<<16],*S,*T;
    if(S==T){T=(S=buf)+fread(buf,1,1<<16,stdin);if(T==S) return EOF;}
    return *S++;
}
inline int read(){
    int x=0,f=1;char ch=gc();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=gc();}
    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=gc();
    return x*f;
}
int n,m,a[N],f[N],sz[N],h[N],num=0,sumsz,rt,dis[N];
bool ans[110],flag[1000100],vis[N];
struct edge{
    int to,next,val;
}data[N<<1];
inline void dfs1(int x,int Fa){
    sz[x]=1;
    for(int i=h[x];i;i=data[i].next){
        int y=data[i].to;if(y==Fa||vis[y]) continue;
        dfs1(y,x);sz[x]+=sz[y];
    }
}
inline void dfs2(int x,int Fa){
    f[x]=0;
    for(int i=h[x];i;i=data[i].next){
        int y=data[i].to;if(y==Fa||vis[y]) continue;
        dfs2(y,x);f[x]=max(f[x],sz[y]);
    }f[x]=max(f[x],sumsz-sz[x]);if(f[x]<f[rt]) rt=x;
}
inline bool dfs3(int x,int Fa,int val){
    if(dis[x]>val) return 0;
    if(flag[val-dis[x]]) return 1;
    for(int i=h[x];i;i=data[i].next){
        int y=data[i].to;if(y==Fa||vis[y]) continue;
        dis[y]=dis[x]+data[i].val;if(dfs3(y,x,val)) return 1;
    }return 0;
}
inline void dfs4(int x,int Fa){
    if(dis[x]>1e6) return;
    flag[dis[x]]=1;
    for(int i=h[x];i;i=data[i].next){
        int y=data[i].to;if(y==Fa||vis[y]) continue;
        dis[y]=dis[x]+data[i].val;dfs4(y,x);
    }
}
inline void dfs5(int x,int Fa){
    if(dis[x]>1e6) return;
    flag[dis[x]]=0;
    for(int i=h[x];i;i=data[i].next){
        int y=data[i].to;if(y==Fa||vis[y]) continue;dfs5(y,x);
    }
}
inline void solve(int x){
    vis[x]=1;dfs1(x,0);dis[x]=0;flag[0]=1;
    for(int i=h[x];i;i=data[i].next){
        int y=data[i].to;if(vis[y]) continue;dis[y]=dis[x]+data[i].val;
        for(int j=1;j<=m;++j){
            if(ans[j]) continue;ans[j]=dfs3(y,x,a[j]);
        }dfs4(y,x);
    }dfs5(x,0);
    for(int i=h[x];i;i=data[i].next){
        int y=data[i].to;if(vis[y]) continue;
        sumsz=sz[y];rt=0;dfs2(y,x);solve(rt);
    }
}
int main(){
//  freopen("a.in","r",stdin);
    n=read();m=read();f[0]=n+1;
    for(int i=1;i<n;++i){
        int x=read(),y=read(),val=read();
        data[++num].to=y;data[num].next=h[x];h[x]=num;data[num].val=val;
        data[++num].to=x;data[num].next=h[y];h[y]=num;data[num].val=val;
    }for(int i=1;i<=m;++i) a[i]=read(),ans[i]=(a[i]?0:1);
    dfs1(1,0);rt=0;sumsz=n;dfs2(1,0);solve(rt);
    for(int i=1;i<=m;++i) puts(ans[i]?"Yes":"No");
    return 0;
}

猜你喜欢

转载自blog.csdn.net/icefox_zhx/article/details/80138564