Luogu 3806 点分治1

Luogu 3806 点分治

  • 要分清楚各个函数的作用及互相调用的关系.
  • 因为是无根树,找重心的时候,父亲一边的所有节点也可以看做是一颗子树.
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define mp make_pair
#define pii pair<int,int>
inline int read()
{
	int x=0;
	bool pos=1;
	char ch=getchar();
	for(;!isdigit(ch);ch=getchar())
		if(ch=='-')
			pos=0;
	for(;isdigit(ch);ch=getchar())
		x=x*10+ch-'0';
	return pos?x:-x;
}
const int MAXN=1e4+10;
const int MAXK=1e7+10;
int n,m;
int ans[MAXK];
int cnt=0,head[MAXN],to[MAXN<<1],nx[MAXN<<1],val[MAXN<<1];
inline void addedge(int u,int v,int w)
{
	++cnt;
	nx[cnt]=head[u];
	to[cnt]=v;
	val[cnt]=w;
	head[u]=cnt;
	swap(u,v);
	++cnt;
	nx[cnt]=head[u];
	to[cnt]=v;
	val[cnt]=w;
	head[u]=cnt;
}
int siz[MAXN],sonsiz[MAXN],vis[MAXN];
int stk[MAXN],tp;
int mi,totsiz,rt;
void getrt(int u,int fa)
{
	siz[u]=1;
	sonsiz[u]=0;
	for(int i=head[u];i;i=nx[i])
		{
			int v=to[i];
			if(vis[v] || v==fa)
				continue;
			getrt(v,u);
			siz[u]+=siz[v];
			sonsiz[u]=max(sonsiz[u],siz[v]);
		}
	sonsiz[u]=max(sonsiz[u],totsiz-siz[u]);
	if(sonsiz[u]<mi)
		mi=sonsiz[u],rt=u;
}
void calc(int u,int fa,int len)
{
	stk[++tp]=len;
	for(int i=head[u];i;i=nx[i])
		{
			int v=to[i];
			if(vis[v] || v==fa)
				continue;
			calc(v,u,len+val[i]);
		}
}
void solve(int rt,int len,int v)
{
	tp=1;
	calc(rt,0,len);
	for(int i=1;i<tp;++i)
		for(int j=i+1;j<=tp;++j)
			ans[ stk[i]+stk[j] ]+=v;
}
#define inf 1e9
void divide(int u)
{
	vis[u]=1;
	solve(u,0,1);
	for(int i=head[u];i;i=nx[i])
		{
			int v=to[i];
			if(vis[v])
				continue;
			solve(v,val[i],-1);
			mi=inf;
			totsiz=siz[v];
			getrt(v,0);
			divide(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);
		}
	rt=0,mi=inf,totsiz=n;
	getrt(1,0);
	divide(rt);
	while(m--)
		{
			int k=read();
			printf("%s
",ans[k]?"AYE":"NAY");
		}
	return 0;
}
原文地址:https://www.cnblogs.com/jklover/p/10396959.html