洛谷 P3806 【模板】点分治1

洛谷 P3806 【模板】点分治1

洛谷传送门

题目描述

给定一棵有 nn 个点的树,询问树上距离为 kk 的点对是否存在。

输入格式

第一行两个数 n,mn,m

第 22 到第 nn 行,每行三个整数 u, v, wu,v,w,代表树上存在一条连接 uu 和 vv 边权为 ww 的路径。

接下来 mm 行,每行一个整数 kk,代表一次询问。

输出格式

对于每次询问输出一行一个字符串代表答案,存在输出 AYE,否则输出 NAY


题解:

看起来像是POI波兰那边的题。

算是点分治的模板?

关于点分治的讲解,请看:

详解点分治

代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
#define N 10001
#define re register 
inline int read()
{
    int x=0,f=1;
    char c=getchar();
    while(c<'0'||c>'9'){
        if(c=='-')f=-1;
        c=getchar();
    }
    while(c>='0'&&c<='9'){
        x=(x<<3)+(x<<1)+c-'0';
        c=getchar();
    }
    return x*f;
}
int n,m,query[101];
int cnt=0,mp[N],size[N],root,tot=0,d[N],b[N],a[N];
bool vis[N],ans[101];
int to[N<<1],nxt[N<<1],head[N],val[N<<1];
void add(int a,int b,int c)
{
	cnt++;
	nxt[cnt]=head[a];
	to[cnt]=b;
	val[cnt]=c;
	head[a]=cnt;
}
void getroot(int x,int fa,int total)
{
	size[x]=1;
	mp[x]=0;
	for(re int i=head[x];i;i=nxt[i])
	{
		int y=to[i];
		if(y==fa||vis[y])
			continue;
		getroot(y,x,total);
		size[x]+=size[y];
		mp[x]=max(size[y],mp[x]);
	}
	mp[x]=max(mp[x],total-size[x]);
	if(!root||mp[x]<mp[root])
		root=x;
}
bool cmp(int x,int y)
{
	return d[x]<d[y];
}
void get_dis(int x,int fa,int dis,int from)
{
	a[++tot]=x;
	d[x]=dis;
	b[x]=from;
	for(re int i=head[x];i;i=nxt[i])
	{
		int y=to[i];
		if(y==fa||vis[y])
			continue;
		get_dis(y,x,dis+val[i],from);
	}
}
void calc(int x)
{
	tot=0;
	a[++tot]=x;
	d[x]=0;
	b[x]=x;
	for(int i=head[x];i;i=nxt[i])
	{
		int y=to[i];
		if(vis[y])
			continue;
		get_dis(y,x,val[i],y);
	}
	sort(a+1,a+tot+1,cmp);
	for(int i=1;i<=m;i++)
	{
		int l=1,r=tot;
		if(ans[i])
			continue;
		while(l<r)
		{
			if(d[a[l]]+d[a[r]]>query[i])
				r--;
			else if(d[a[l]]+d[a[r]]<query[i])
				l++;
			else if(b[a[l]]==b[a[r]])
			{
				if(d[a[r]]==d[a[r-1]])
					r--;
				else 
					l++;
			}
			else
			{
				ans[i]=1;
				break;
			}
		}
	}
}
void dfz(int x)
{
	vis[x]=1;
	calc(x);
	for(re int i=head[x];i;i=nxt[i])
	{
		int y=to[i];
		if(vis[y])
			continue;
		root=0;
		getroot(y,0,size[y]);
		dfz(root);
	}
}
int main()
{
	n=read(),m=read();
	for(re int i=1;i<n;i++)
	{
		int x,y,w;
		x=read(),y=read(),w=read();
		add(x,y,w);
		add(y,x,w);
	}
	for(re int i=1;i<=m;i++)
	{
		query[i]=read();
		if(!query[i])
			ans[i]=1;
	}
	mp[0]=n;
	getroot(1,0,n);
	dfz(root);
	for(re int i=1;i<=m;i++)
		if(ans[i])
			puts("AYE");
		else
			puts("NAY");
	return 0;
}
原文地址:https://www.cnblogs.com/fusiwei/p/13822620.html