[luogu3806]【模板】点分治1
description
求树上长度为\(k\)的路径是否存在。
data range
\]
solution
点分治复习。。。
使用普通的点分治枚举路径模板即可。
一个小细节
本人初学点分治的时候是这样写的
int sum,rt,sz[N],w[N];bool vis[N];
void getrt(int u,int ff){//找到对应连通块的重心
sz[u]=1;w[u]=0;
for(RG int i=head[u];i;i=nxt[i]){
RG int v=to[i];if(v==ff||vis[v])continue;
getrt(v,u);sz[u]+=sz[v];
w[u]=max(w[u],sz[v]);
}
w[u]=max(w[u],blk-sz[u]);
if(w[rt]>w[u])rt=u;
}
void solve(int u){//递归分治
vis[u]=1;
for(RG int i=head[u];i;i=nxt[i]){
RG int v=to[i];if(vis[v])continue;
rt=0;blk=sz[v];
getrt(v,0);
solve(rt);
}
}
int main()
{
//...
rt=0;w[0]=sum=n;
getrt(1,0);
solve(rt);
return 0;
}
现在感觉这样写有问题。
关键出在直接赋值\(sum=sz[v]\)上。
给出一棵树:

我们第一次选择的重心是节点\(3\)
然而这时\(sz[1]=6\)
于是我们递归解决上面部分的时候重心就会受到影响
然后就可能会\(T\)
解决方法是两边\(dfs\)像这样似乎常数又加大了:
int sum,rt,sz[N],w[N];bool vis[N];
void getrt(int u,int ff){//找到对应连通块的重心
sz[u]=1;w[u]=0;
for(RG int i=head[u];i;i=nxt[i]){
RG int v=to[i];if(v==ff||vis[v])continue;
getrt(v,u);sz[u]+=sz[v];
w[u]=max(w[u],sz[v]);
}
w[u]=max(w[u],blk-sz[u]);
if(w[rt]>w[u])rt=u;
}
void solve(int u){//递归分治
vis[u]=1;
for(RG int i=head[u];i;i=nxt[i]){
RG int v=to[i];if(vis[v])continue;
rt=0;blk=sz[v];
getrt(v,0);
getrt(rt,0);//第二遍dfs
solve(rt);
}
}
int main()
{
//...
rt=0;w[0]=sum=n;
getrt(1,0);
getrt(rt,0);//第二遍dfs
solve(rt);
return 0;
}
Code
#include<bits/stdc++.h>
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<iomanip>
#include<cstring>
#include<complex>
#include<vector>
#include<cstdio>
#include<string>
#include<bitset>
#include<ctime>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#define Cpy(x,y) memcpy(x,y,sizeof(x))
#define Set(x,y) memset(x,y,sizeof(x))
#define FILE "a"
#define mp make_pair
#define pb push_back
#define RG register
#define il inline
using namespace std;
typedef unsigned long long ull;
typedef vector<int>VI;
typedef long long ll;
typedef double dd;
const int N=10010;
const int M=10000010;
const dd eps=1e-5;
const int inf=2147483647;
const ll INF=1ll<<60;
const ll P=100000;
il ll read(){
RG ll data=0,w=1;RG char ch=getchar();
while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
if(ch=='-')w=-1,ch=getchar();
while(ch<='9'&&ch>='0')data=data*10+ch-48,ch=getchar();
return data*w;
}
il void file(){
srand(time(NULL)+rand());
freopen(FILE".in","r",stdin);
freopen(FILE".out","w",stdout);
}
int n,m,rt,blk,k,flg;
int head[N],nxt[N<<1],to[N<<1],val[N<<1],cnt;
il void add(int u,int v,int w){
to[++cnt]=v;val[cnt]=w;nxt[cnt]=head[u];head[u]=cnt;
}
int sz[N],w[N];bool vis[N],tong[M];
void getrt(int u,int ff){
sz[u]=1;w[u]=0;
for(RG int i=head[u];i;i=nxt[i]){
RG int v=to[i];if(v==ff||vis[v])continue;
getrt(v,u);sz[u]+=sz[v];
w[u]=max(w[u],sz[v]);
}
w[u]=max(w[u],blk-sz[u]);
if(w[rt]>w[u])rt=u;
}
int dep[N],cal[N],top;
void getdep(int u,int ff){
cal[++top]=dep[u];
for(RG int i=head[u];i;i=nxt[i]){
RG int v=to[i];if(v==ff||vis[v])continue;
dep[v]=dep[u]+val[i];if(dep[v]<=k)getdep(v,u);
}
}
void getcl(int u,int ff){
tong[dep[u]]=0;
for(RG int i=head[u];i;i=nxt[i]){
RG int v=to[i];if(v==ff||vis[v])continue;
getcl(v,u);
}
}
void solve(int u){
vis[u]=1;dep[u]=0;cal[++top]=0;
for(RG int i=head[u];i;i=nxt[i]){
RG int v=to[i];if(vis[v])continue;
dep[v]=dep[u]+val[i];getdep(v,u);
for(RG int j=1;j<=top;j++)
if(tong[k-cal[j]]||cal[j]==k)flg=1;
for(RG int j=1;j<=top;j++)
tong[cal[j]]=1;
top=0;
}
getcl(u,0);
for(RG int i=head[u];i;i=nxt[i]){
RG int v=to[i];if(vis[v])continue;
rt=0;blk=sz[v];
getrt(v,0);
getrt(rt,0);
solve(rt);
}
}
int main()
{
n=read();m=read();
for(RG int i=1,u,v,w;i<n;i++){
u=read();v=read();w=read();
add(u,v,w);add(v,u,w);
}
for(RG int i=1;i<=m;i++){
k=read();flg=0;
memset(vis,0,sizeof(vis));
rt=0;blk=w[0]=n;
getrt(1,0);
getrt(rt,0);
solve(rt);
flg?puts("AYE"):puts("NAY");
}
return 0;
}
[luogu3806]【模板】点分治1的更多相关文章
- 【Luogu3806】点分治(点分治)
[Luogu3806]点分治(点分治) 题面 题目描述 给定一棵有n个点的树 询问树上距离为k的点对是否存在. 输入格式: n,m 接下来n-1条边a,b,c描述a到b有一条长度为c的路径 接下来m行 ...
- 洛谷 P4721 【模板】分治 FFT 解题报告
P4721 [模板]分治 FFT 题目背景 也可用多项式求逆解决. 题目描述 给定长度为 \(n−1\) 的数组 \(g[1],g[2],\dots,g[n-1]\),求 \(f[0],f[1],\d ...
- luoguP4721 【模板】分治 FFT
P4721 [模板]分治 FFT 链接 luogu 题目描述 给定长度为 \(n-1\) 的数组 \(g[1],g[2],..,g[n-1]\),求 \(f[0],f[1],..,f[n-1]\),其 ...
- LG4721 【模板】分治 FFT
P4721 [模板]分治 FFT 题目背景 也可用多项式求逆解决. 题目描述 给定长度为 $n-1$ 的数组 $g[1],g[2],..,g[n-1]$,求 $f[0],f[1],..,f[n-1]$ ...
- 模板·点分治(luogu P3806)
[模板]洛谷·点分治 1.求树的重心 树的重心:若A点的子树中最大的子树的size[] 最小时,A为该树的中心 步骤: 所需变量:siz[x] 表示 x 的子树大小(含自己),msz[x] 表示 其子 ...
- 【洛谷4721】【模板】分治FFT(CDQ分治_NTT)
题目: 洛谷 4721 分析: 我觉得这个 "分治 FFT " 不能算一种特殊的 FFT ,只是 CDQ 分治里套了个用 FFT (或 NTT)计算的过程,二者是并列关系而不是偏正 ...
- [模板] CDQ分治&&BZOJ3262:陌上花开
简介 CDQ分治是分治的一种, 可以看做归并排序的扩展, 利用离线将一些 \(O(n)\) 的暴力优化到 \(O(log n)\). 它可以用来顶替一些高级(log)数据结构等. 一般地, CDQ分治 ...
- P4721【模板】分治 FFT
瞎扯 虽然说是FFT但是还是写了一发NTT(笑) 然后忘了IDFT之后要除个n懵逼了好久 以及递归的时候忘了边界无限RE 思路 朴素算法 分治FFT 考虑到题目要求求这样的一个式子 \[ F_x=\S ...
- P4721 【模板】分治 FFT
其实是分治ntt,因为fft会爆精度,真*裸题 分治过程和fft的一模一样,主要就是ntt精度高,用原根来代替fft中的\(w_n^k\) 1.定义:设m>1,(a,m)==1,满足\(a^r= ...
- [洛谷P4721]【模板】分治 FFT_求逆
题目大意:给定长度为$n-1$的数组$g_{[1,n)}$,求$f_{[0,n)}$,要求: $$f_i=\sum_{j=1}^if_{i-j}g_j\\f_0=1$$ 题解:分治$FFT$博客,发现 ...
随机推荐
- tarjan算法求最近公共祖先
tarjian算法 LCA: LCA(Least Common Ancestor),顾名思义,是指在一棵树中,距离两个点最近的两者的公共节点.也就是说,在两个点通往根的道路上,肯定会有公共的节点,我们 ...
- hive中 udf,udaf,udtf
1.hive中基本操作: DDL,DML 2.hive中函数 User-Defined Functions : UDF(用户自定义函数,简称JDF函数)UDF: 一进一出 upper lower ...
- 屏蔽Drupal中的“Notice: Undefined index”警告
原因:drupal默认使用E_ALL,即输出所有错误和警告.我们只需要修改错误显示级别即可. 方法: 1. 打开\sites\default\settings.php 追加一行 ini_set('er ...
- jenkins通过maven指定testng的xml文件,并给testng代码传参
1.jenkins设置参数化构建,设置要传的参数名和值 2.指定testng的xml文件,在jenkins的输入以下 3.在pom.xml文件分别引用jenkins的参数,设置两个property & ...
- hdu6027Easy Summation(快速幂取模)
Easy Summation Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others) ...
- web自动化测试框架总结
web自动化测试框架总结: https://www.processon.com/mindmap/5bdab924e4b0878bf41e9e09
- 内置方法(item系列)
class Foo: def __init__(self,name): self.name = name def __getitem__(self, item): # 获取时触发 print('get ...
- Java开发工程师(Web方向) - 02.Servlet技术 - 期末考试
Servlet课程考试 Servlet课程考试 Servlet课程考试 总分:55分 限定时间:120分钟 进入考试 答案已成功提交!请耐心等待成绩公布 Servlet课程考试: 1(12分) 简单谈 ...
- 【system.file】使用说明
对象:system.file 说明:提供一系列针对文件操作的方法. 注意:参数中的filePath 均为相对网站根目录路径 目录: 方法 返回 说明 system.file.exists(filePa ...
- 407. Plus One【LintCode java】
Description Given a non-negative number represented as an array of digits, plus one to the number. T ...