zoukankan      html  css  js  c++  java
  • P3806 【模板】点分治1

    题目

    P3806 【模板】点分治1

    定一棵有 (n) 个点的树,多次询问树上距离为 (k) 的点对是否存在。

    分析

    淀粉质模板题。

    淀粉质的核心就是其只统计经过当前根结点的路径,即可以把两条路径“拼”起来,同时分治结构保证了其只有 (log) 次这样的计算。

    常用于统计树上点对数量这样的问题。

    来看这道题。

    可以对每一个路径长度开一个桶来存有多少条,但是这里是多次询问,于是我们每一次要遍历所有询问来查找桶。

    具体可以见代码:

    #include<bits/stdc++.h>
    using namespace std;
    template <typename T>
    inline void read(T &x){
        x=0;char ch=getchar();bool f=false;
        while(!isdigit(ch)) f|=ch=='-',ch=getchar();
        while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
        x=f?-x:x;return;
    }
    template <typename T>
    inline void write(T x){
        if(x<0) putchar('-'),x=-x;
        if(x>9) write(x/10);
        putchar(x%10^48);return;
    }
    #define ll long long
    const int N=1e5+5,M=1e7+5;
    int n,m;
    int head[N],nex[N],to[N],val[N],idx;
    bool vis[N],Vis[N],app[M],Ans[N];
    int Q[N],path[N],clear[N],siz[N];
    int Root,NowMax,path_cnt,Cnt,Size;
    inline void add(int u,int v,int w){
    	nex[++idx]=head[u];
    	to[idx]=v;
    	val[idx]=w;
    	head[u]=idx;
    	return ;
    }
    void FindRoot(int x){
    	vis[x]=true;siz[x]=1;int Max=0;
    	for(int i=head[x];i;i=nex[i]){
    		int y=to[i];
    		if(vis[y]||Vis[y]) continue;
    		FindRoot(y);siz[x]+=siz[y];
    		Max=max(siz[y],Max);
    	}
    	Max=max(Size-siz[x],Max);
    	if(Max<NowMax) NowMax=Max,Root=x;
    	vis[x]=false;
    	return ;
    }
    void GetPath(int x,int D){
    	path[++path_cnt]=D;vis[x]=true;siz[x]=1;
    	for(int i=head[x];i;i=nex[i]){
    		int y=to[i];
    		if(vis[y]||Vis[y]) continue;
    		GetPath(y,D+val[i]);siz[x]+=siz[y];
    	}
    	vis[x]=false;
    	return ;
    }
    void DFS(int x){
    	Vis[x]=true;Cnt=0;
    	for(int i=head[x];i;i=nex[i]){
    		int y=to[i];
    		if(Vis[y]) continue;
    		path_cnt=0;GetPath(y,val[i]);
    		for(int j=1;j<=m;j++){
    			for(int k=1;k<=path_cnt;k++){
    				if(Q[j]>=path[k]&&app[Q[j]-path[k]]) Ans[j]=true;
    			}
    		}
    		for(int j=1;j<=path_cnt;j++) if(path[j]<M) app[path[j]]=true,clear[++Cnt]=path[j];
    	}
    	for(int i=1;i<=Cnt;i++) app[clear[i]]=false;
    	for(int i=head[x];i;i=nex[i]){
    		int y=to[i];
    		if(Vis[y]) continue;
    		Size=siz[y],NowMax=n,Root=0,FindRoot(y);DFS(Root);
    	}
    	return ;
    }
    
    signed main(){
    	read(n),read(m);
    	for(int i=1;i<n;i++){
    		int u,v,w;
    		read(u),read(v),read(w);
    		add(u,v,w),add(v,u,w);
    	}
    	app[0]=true;
    	for(int i=1;i<=m;i++) read(Q[i]); 
    	Size=n,NowMax=n,Root=0,FindRoot(1),DFS(Root);
    	for(int i=1;i<=m;i++) puts(Ans[i]?"AYE":"NAY");
    	return 0;
    }
    
  • 相关阅读:
    【typecho】解决使用分隔符 <!--more-->标签后首页文字下面出现一段空白
    真没想到,疫情让我实现了远程办公的夙愿
    程序员周末应该干的8件事
    在Delphi中如何控制其它应用程序窗口
    Delphi 如何操作外部程序的控件(如按钮,文本框,单选按钮等)
    delphi 向其他程序发送模拟按键
    Delphi中如何控制其他程序窗体上的窗口控件
    用Delphi“遥控”按钮
    双系统启动菜单的修改方法
    PureBasic 读取文件中一行的两个数据例子
  • 原文地址:https://www.cnblogs.com/Akmaey/p/14726790.html
Copyright © 2011-2022 走看看