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. Farpoint使用一点小总结

    Farpoint表格编辑的功能是非常强大的,记录下自己常用到的地方. 使用的版本:FarPoint.Win.Spread.5.0 1.Farpoint 设置为不可编辑状态 this.FPProxyIt ...

  2. 「知识学习」二分图的最大匹配、完美匹配和匈牙利算法(HDU-2063)

    定义 如果一个图\((E,V)\)的顶点集\(E\)能够被能够被分成两个不相交的集合\(X,Y\),且每一条边都恰连接\(X,Y\)中的各一个顶点,那么这个图就是一个二分图. 容易得知,它就是不含有奇 ...

  3. 【view】 视图组件说明

    view 是视图容器,可用于包裹其它组件或文本内容. 原型: <view hover-class="[String]" hover-stop-propagation=&quo ...

  4. 孤荷凌寒自学python第八十四天搭建jTessBoxEditor来训练tesseract模块

    孤荷凌寒自学python第八十四天搭建jTessBoxEditor来训练tesseract模块 (完整学习过程屏幕记录视频地址在文末) 由于本身tesseract模块针对普通的验证码图片的识别率并不高 ...

  5. 利用人脸特征提取DeepID--解读世纪晟人脸识别

    概述:DeepID的目标是人脸验证(判断两张图片是否是一个人),同时衍生出人脸识别(多次人脸验证). DeepID采用增大数据集的方法: 增加新的数据,celebFaces(87628张图片,5436 ...

  6. BZOJ 4736 温暖会指引我们前行 LCT+最优生成树+并查集

    题目链接:http://uoj.ac/problem/274 题意概述: 没什么好概述的......概述了题意就知道怎么做了......我懒嘛 分析: 就是用lct维护最大生成树. 然后如果去UOJ上 ...

  7. Windows Phone编程回顾

    前言 已有一年多没有碰WP相关的开发了. 近期经常看博客园的文章, 发现开发WP应用的同学很多, 其中博问频道关于"WPF", "C#", "WP8& ...

  8. Python 服务器端表单验证插件

    Python格式验证库 Cerberus 作者 MrStranger 关注 2016.08.02 14:44 字数 2140 阅读 79评论 0喜欢 1 Cerberus是一个验证Python对象.M ...

  9. k邻近算法理解及代码实现

    github:代码实现 本文算法均使用python3实现 1 KNN   KNN(k-nearest neighbor, k近邻法),故名思议,是根据最近的 $ k $ 个邻居来判断未知点属于哪个类别 ...

  10. TCP系列30—窗口管理&流控—4、Cork算法

    一.Cork算法概述 Cork算法与Nagle算法类似,也有人把Cork算法称呼为super-Nagle.Nagle算法提出的背景是网络因为大量小包小包而导致利用率低下产生网络拥塞,网络发生拥塞的时候 ...