点分治食用

洛谷日报
点分治1

将块想象为树枝,由高级点向低级点分子树,最后分成n个点,暴力求解

  • Get_rt
    找到当前分治树的重心
    use[v]=>防止从更优级分治的点(祖先)的越界

inline void Get_rt(int x,int fa)
{
	f[x]=0;size[x]=1;
	for(int i=hd[x];i;i=e[i].nt)
	{
		int v=e[i].to;
		if(use[v]||v==fa)continue;
		
		Get_rt(v,x);
		size[x]+=size[v];
		f[x]=max(f[x],size[v]);
	}
	f[x]=max(f[x],SIZE-size[x]);
	if(f[x]<f[rt])rt=x;
}

  • Dfs:分治
    pc[0]=1;可能有边权为0的点
    cala:计算当前分治结果
inline void dfs(int x)
{
	use[x]=1;pc[0]=1;
	cala(x);
	for(int i=hd[x];i;i=e[i].nt)
	{
		int v=e[i].to;
		if(use[v])continue;
		f[rt=0]=n;SIZE=size[v];
		Get_rt(v,x);
		dfs(rt);
	}
}
  • Cala
inline void cala(int x)
{
	int p=0;
	int c[maxn];//记录当前分治下存在路径情况
	for(int i=hd[x];i;i=e[i].nt)
	{
		int v=e[i].to;
		if(use[v])continue;
		cnt[0]=0;//统计路个数
		//cnt:统计路径长度
		dis[v]=e[i].val;
		//分治初始路径长度
		Get_dis(v,x);
		//得到路径长度
		
		for(int j=1;j<=cnt[0];++j)
		for(int k=1;k<=m;++k)
			if(q[k]>=cnt[j])ans[k]|=pc[q[k]-cnt[j]];
			//与答案匹配
		
		for(int j=1;j<=cnt[0];++j)
		 c[++p]=cnt[j],pc[cnt[j]]=1;
		 //分治点内打标记
	}
	
	inc(i,1,p)pc[c[i]]=0;
	//还原,为了下次使用 
}
  • Get_dis
    累加求长度
inline void Get_dis(int x,int fa)
{
	cnt[++cnt[0]]=dis[x];
	for(int i=hd[x];i;i=e[i].nt)
	{
		int v=e[i].to;
		if(use[v]||v==fa)continue;
		dis[v]=dis[x]+e[i].val;
		Get_dis(v,x);
	}
}

完整代码

#include<bits/stdc++.h>
#define re return
#define inc(i,l,r) for(int i=l;i<=r;++i)
const int maxn=1e5+5,maxm=305;

using namespace std;
template<typename T>inline void rd(T&x)
{
	char c;bool f=0;
	while((c=getchar())<'0'||c>'9')if(c=='-')f=1;
	x=c^48;
	while((c=getchar())>='0'&&c<='9')x=x*10+(c^48);
	if(f)x=-x; 
} 

int size[maxn],n,m,dis[maxn],rt,SIZE,hd[maxn],f[maxn],pc[maxn];
int k,cnt[maxn],q[maxn],use[maxn],ans[maxn];
struct node{
	int to,nt,val;
}e[maxn<<1];

inline void add(int x,int y,int z)
{
	e[++k].to=y;e[k].nt=hd[x];hd[x]=k;e[k].val=z;
	e[++k].to=x;e[k].nt=hd[y];hd[y]=k;e[k].val=z;
}

inline void Get_rt(int x,int fa)
{
	f[x]=0;size[x]=1;
	for(int i=hd[x];i;i=e[i].nt)
	{
		int v=e[i].to;
		if(use[v]||v==fa)continue;
		
		Get_rt(v,x);
		size[x]+=size[v];
		f[x]=max(f[x],size[v]);
	}
	f[x]=max(f[x],SIZE-size[x]);
	if(f[x]<f[rt])rt=x;
}

inline void Get_dis(int x,int fa)
{
	cnt[++cnt[0]]=dis[x];
	for(int i=hd[x];i;i=e[i].nt)
	{
		int v=e[i].to;
		if(use[v]||v==fa)continue;
		dis[v]=dis[x]+e[i].val;
		Get_dis(v,x);
	}
}

inline void cala(int x)
{
	int p=0;
	int c[maxn];
	for(int i=hd[x];i;i=e[i].nt)
	{
		int v=e[i].to;
		if(use[v])continue;
		cnt[0]=0;dis[v]=e[i].val;
		Get_dis(v,x);
		
		for(int j=1;j<=cnt[0];++j)
		for(int k=1;k<=m;++k)
			if(q[k]>=cnt[j])ans[k]|=pc[q[k]-cnt[j]];
		
		for(int j=1;j<=cnt[0];++j)
		 c[++p]=cnt[j],pc[cnt[j]]=1;
	}
	
	inc(i,1,p)pc[c[i]]=0; 
}

inline void dfs(int x)
{
	use[x]=1;pc[0]=1;
	cala(x);
	for(int i=hd[x];i;i=e[i].nt)
	{
		int v=e[i].to;
		if(use[v])continue;
		f[rt=0]=n;SIZE=size[v];
		Get_rt(v,x);
		dfs(rt);
	}
}

int main()
{
	freopen("in.txt","r",stdin);
	
	int x,y,z;
	rd(n),rd(m);
	inc(i,2,n)
	{
		rd(x),rd(y),rd(z);
		add(x,y,z); 
	}
	inc(i,1,m)rd(q[i]);
	
	f[rt]=SIZE=n;
	Get_rt(1,0);
	
	dfs(rt);
	
	inc(i,1,m)
	if(ans[i])
	   printf("AYE
");
	else printf("NAY
");
	re 0;
} 
原文地址:https://www.cnblogs.com/lsyyy/p/11287638.html