description

求树上长度为\(k\)的路径是否存在。

data range

\[n\le 10000,k\le 10000000
\]

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的更多相关文章

  1. 【Luogu3806】点分治(点分治)

    [Luogu3806]点分治(点分治) 题面 题目描述 给定一棵有n个点的树 询问树上距离为k的点对是否存在. 输入格式: n,m 接下来n-1条边a,b,c描述a到b有一条长度为c的路径 接下来m行 ...

  2. 洛谷 P4721 【模板】分治 FFT 解题报告

    P4721 [模板]分治 FFT 题目背景 也可用多项式求逆解决. 题目描述 给定长度为 \(n−1\) 的数组 \(g[1],g[2],\dots,g[n-1]\),求 \(f[0],f[1],\d ...

  3. luoguP4721 【模板】分治 FFT

    P4721 [模板]分治 FFT 链接 luogu 题目描述 给定长度为 \(n-1\) 的数组 \(g[1],g[2],..,g[n-1]\),求 \(f[0],f[1],..,f[n-1]\),其 ...

  4. LG4721 【模板】分治 FFT

    P4721 [模板]分治 FFT 题目背景 也可用多项式求逆解决. 题目描述 给定长度为 $n-1$ 的数组 $g[1],g[2],..,g[n-1]$,求 $f[0],f[1],..,f[n-1]$ ...

  5. 模板·点分治(luogu P3806)

    [模板]洛谷·点分治 1.求树的重心 树的重心:若A点的子树中最大的子树的size[] 最小时,A为该树的中心 步骤: 所需变量:siz[x] 表示 x 的子树大小(含自己),msz[x] 表示 其子 ...

  6. 【洛谷4721】【模板】分治FFT(CDQ分治_NTT)

    题目: 洛谷 4721 分析: 我觉得这个 "分治 FFT " 不能算一种特殊的 FFT ,只是 CDQ 分治里套了个用 FFT (或 NTT)计算的过程,二者是并列关系而不是偏正 ...

  7. [模板] CDQ分治&&BZOJ3262:陌上花开

    简介 CDQ分治是分治的一种, 可以看做归并排序的扩展, 利用离线将一些 \(O(n)\) 的暴力优化到 \(O(log n)\). 它可以用来顶替一些高级(log)数据结构等. 一般地, CDQ分治 ...

  8. P4721【模板】分治 FFT

    瞎扯 虽然说是FFT但是还是写了一发NTT(笑) 然后忘了IDFT之后要除个n懵逼了好久 以及递归的时候忘了边界无限RE 思路 朴素算法 分治FFT 考虑到题目要求求这样的一个式子 \[ F_x=\S ...

  9. P4721 【模板】分治 FFT

    其实是分治ntt,因为fft会爆精度,真*裸题 分治过程和fft的一模一样,主要就是ntt精度高,用原根来代替fft中的\(w_n^k\) 1.定义:设m>1,(a,m)==1,满足\(a^r= ...

  10. [洛谷P4721]【模板】分治 FFT_求逆

    题目大意:给定长度为$n-1$的数组$g_{[1,n)}$,求$f_{[0,n)}$,要求: $$f_i=\sum_{j=1}^if_{i-j}g_j\\f_0=1$$ 题解:分治$FFT$博客,发现 ...

随机推荐

  1. JDBC事务机制

    package com.jdbc.test; import java.sql.*; /** * 数据库的引擎必须是innodb */ public class Demo02 { PreparedSta ...

  2. windown reids

    记录Windown安装Redis和php_redis扩展 和Linux系统不同windown中不需要编译安装:只需要下对版本拖拽过去即可: 首先安装redis服务: 可以百度下一个,只要注意系统版本即 ...

  3. jmeter常用测试元件

    1.线程组 线程组是任何测试计划的起点,所有的逻辑控制器和采样器都必须放在线程组下.其他的测试元件(例如监听器)可以直接放在测试计划下,这些测试元件对所有的线程组都生效. 每一个JMeter线程都会完 ...

  4. DEDEcms调用当前栏目顶级栏目url地址

    include/common.func.php 找到这个文件 在文件最下方加入以下代码: //获取顶级栏目url function GetTopTypeurl($id) { global $dsql; ...

  5. APP功能性测试-1

    疑难点 根据软件说明()或用户需求()验证App的各个功能实现 根据需求,提炼App的用户使用场景,验证功能 根据测试指标,验证功能 根据被测试功能点的特性采用特定的方法进行测试(场景,边界值,,,) ...

  6. .NET MVC和.NET WEB api混用时注意事项

    1.同时配置了mvc路由和api路由时,mvc路由无法访问(调用所有mvc路由全部404错误) 在Global.asax中,需注意路由注册的顺序,将api路由注册放在最后: 即将 void Appli ...

  7. word record 3

    word record 3 tabloid : a half size page of a newspaper, or a newspaper or magazine with short, exci ...

  8. JS获取HTML DOM元素的8种方法

    什么是HTML DOM 文档对象模型(Document Object Model),是W3C组织推荐的处理可扩展置标语言的标准编程接口.简单理解就是HTML DOM 是关于如何获取.修改.添加或删除 ...

  9. python同时遍历两个list

    两个list, 有对应关系,希望同时完成遍历 用迭代器迭代的方法也不是不可以,python提供了更直观的方法: 可以使用zip把两个list打包 , 类似: list1 = [1,2,3,4] lis ...

  10. Memcache的客户端连接系列(一) Java

    声明:本文并非原创,转自华为云帮助中心的分布式缓存服务(Memcached)的用户指南. 关键词: Memcached  客户端 Java Java连接池 Java客户端示例 用户的弹性云服务器已安装 ...