P3806 【模板】点分治1
作者:互联网
题目背景
感谢hzwer的点分治互测。
题目描述
给定一棵有n个点的树
询问树上距离为k的点对是否存在。
输入输出格式
输入格式:n,m 接下来n-1条边a,b,c描述a到b有一条长度为c的路径
接下来m行每行询问一个K
输出格式:对于每个K每行输出一个答案,存在输出“AYE”,否则输出”NAY”(不包含引号)
输入输出样例
输入样例#1:2 1 1 2 2 2输出样例#1:
AYE
说明
对于30%的数据n<=100
对于60%的数据n<=1000,m<=50
对于100%的数据n<=10000,m<=100,c<=10000,K<=10000000
代码
对于每个点,分为有长度为k的路径经过点以及长度为k的路径在其子树
对于长度为k的路径在其子树的点,我们可以将其看作是长度为k的路径经过其子树所在根节点
那么这就是点分治的基本思想
为降低复杂度,我们每次采取重心作为根节点。将树的深度将至logn
则复杂度为O(NlogN2)
#include<bits/stdc++.h> #define inf 0x3f3f3f3f using namespace std; const int maxn=10000+100,maxm=10000000+100; int head[maxn]; int q[maxn],ans[maxn]; int p[maxm],t[maxn]; int d[maxn],dis[maxn],vis[maxn]; int s[maxn],ms[maxn]; int rt=0,sum; int n,m; struct edge { int to,next,val; }e[maxn<<1]; int size=0; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();} return x*f; } void addedge(int u,int v,int w) { e[++size].to=v;e[size].val=w;e[size].next=head[u];head[u]=size; } void tc(int u,int fa)//树的重心 { s[u]=1;ms[u]=0; for(int i=head[u];i;i=e[i].next) { int to=e[i].to; if(to==fa||vis[to])continue; tc(to,u); s[u]+=s[to]; ms[u]=max(ms[u],s[to]); } ms[u]=max(ms[u],sum-ms[u]); if(ms[u]<ms[rt])rt=u; } void dfs(int u,int fa) { d[++d[0]]=dis[u]; for(int i=head[u];i;i=e[i].next) { int to=e[i].to; if(to==fa||vis[to])continue; dis[to]=dis[u]+e[i].val; dfs(to,u); } } void cal(int u) { int tot=0; for(int i=head[u];i;i=e[i].next) { int to=e[i].to; if(vis[to])continue; d[0]=0;dis[to]=e[i].val; dfs(to,u); for(int j=1;j<=d[0];++j) for(int k=1;k<=m;++k) if(!ans[k]&&q[k]>=d[j])//有长度为q[k]的路径:该子树与之前其他子树距离和为q[k] ans[k]=p[q[k]-d[j]]; for(int j=1;j<=d[0];++j) t[++tot]=d[j],p[d[j]]=1;//用桶存下到该节点已有的距离 } for(int i=1;i<=tot;i++) p[t[i]]=0;//桶清空,用memsetTLE } void solve(int u) { vis[u]=p[0]=1;cal(u); for(int i=head[u];i;i=e[i].next) { int to=e[i].to; if(vis[to])continue; sum=s[to],ms[rt=0]=inf; tc(to,0);solve(rt); } } int main() { n=read(),m=read(); for(int i=1;i<n;i++) { int u=read(),v=read(),w=read(); addedge(u,v,w); addedge(v,u,w); } for(int i=1;i<=m;i++) q[i]=read(); sum=n;ms[rt]=inf; tc(1,0); solve(rt); for(int i=1;i<=m;i++) puts(ans[i]?"AYE":"NAY"); return 0; }View Code
标签:ch,int,样例,分治,路径,maxn,长度,P3806,模板 来源: https://www.cnblogs.com/DriverBen/p/10963438.html