首页 > 其他分享 >点分治

点分治

时间:2023-11-23 13:24:05浏览次数:25  
标签:第一种 求解 int 复杂度 分治 maxn

点分治是一种在树上进行的分治,可以方便的求解树上路径等问题。

例题:P3806 【模板】点分治 1

给定一棵树,询问树上是否存在长度为k的路径。
现在我们假设x为根节点,
那么一条路径长度为k有两种情况,
一种是经过x,一种不经过x,
第一种的两个端点在两个不同子树中,
第二种的两个端点在同一子树中,
那么我们选择求解第一种,
第二种也就变成了子问题分治解决。

为了使第一种的求解尽量的快速,我们需要对一颗树以它的重心为根,
这样就可以把复杂度均摊,
假如计算的复杂度为\(O(n)\)(n为树点数),
那么总共的复杂度为\(O(nlog^2n)\).

框架如下:

#include<algorithm>
#include<stdio.h>
#define maxn 100005
using namespace std;
int n;
int head[maxn],to[maxn<<1],nex[maxn<<1],len[maxn<<1],m1;
void add(int u,int v,int w) {
	to[++m1]=v,nex[m1]=head[u],len[m1]=w,head[u]=m1;
}
int vis[maxn],son[maxn];
int root,minn=1e9;
void getroot(int now,int last,int siz) {
	int num=0; son[now]=1;
	for(int i=head[now];i;i=nex[i]) {
		int st=to[i]; if(st==last || vis[st]) continue;
		getroot(st,now,siz);
		num=max(num,son[st]);
		son[now]+=son[st];
	}	
	num=max(num,siz-son[now]);
	if(num<minn) minn=num,root=now;
}
void calc(int now) {
	
}
void solve(int now) {
	vis[now]=1;
	calc(now);
	for(int i=head[now];i;i=nex[i]) {
		int st=to[i]; if(vis[st]) continue;
		minn=1e9; getroot(st,now,son[st]);
		solve(root);
	}
}
int main() {
	freopen(".in","r",stdin);
	freopen(".out","w",stdout);
	scanf("%d",&n);
	for(int i=1;i<n;i++) {
		int u,v,w; scanf("%d%d%d",&u,&v,&w);
		add(u,v,w),add(v,u,w);
	}
	getroot(1,0,n);
	solve(root);
	return 0;
}

标签:第一种,求解,int,复杂度,分治,maxn
From: https://www.cnblogs.com/1n87/p/17851328.html

相关文章

  • 分治与归并
    归并算法:递归+合并,在递归的途中进行分治。递归会把区间越分越小,此时就可以进行分治操作。可以使用全局变量进行分治操作。可以在函数中进行分治操作,在递归树中实现pushup和pushdown,记性父节点与子节点的关系计算。  classSolution{public:structNode{......
  • 点分治学习笔记(未完成)
    前言点分治不应该算数据结构,它的本质是分治的思想。问题引入对于一个序列\(a\),求是否存在\((l,r)\)使得\(\sum\limits_{i=l}^{r}a_i=k\)。\(n\le10^6,|a_i|\le10^9\)。本题显然是有其它的做法的,由于学的是点分治,所以考虑分治做法。首先对\(a\)求前缀和,记这个数组为......
  • 算法学习笔记(1):CDQ分治
    CDQ分治对比普通分治把一种问题划分成不同子问题,递归处理子问题内部的答案,再考虑合并子问题的答案。再看CDQ分治有广泛的应用,但我不会。但在接下来的题目体会到大概:将可能产生的对于答案的贡献分为两类:\(f(l,mid)\)与\(f(mid+1,r)\)内部产生的贡献,其贡献已在递......
  • 根号分治
    Problem给定一个长度为\(S\)字符串\(s\)与一个正整数\(q\),接下来有\(q\)次询问,第\(i\)次询问给出一个长度为\(T_i\)字符串\(t_i\),求\(t_i\)在\(s\)的出现次数。保证\(S,q,\sum^q_{i=1}T_i\leq10^5\)。Solution后缀自动机,但是我不会。注意到\(\sum^q_{i=1}......
  • 分治算法(C语言)
    一、棋盘覆盖问题1、问题2、分析(1)当k>0时,将2k×2k棋盘分割为4个(2k-1)×(2k-1)子棋盘,如图(a)所示。每一次分解,都将原本大小的棋盘,划分为四份,即行号和列号各自缩减一半。(2)特殊方格必位于4个较小子棋盘之一中,其余3个子棋盘中无特殊方格。(3)为将无特殊方格子棋盘转化为特......
  • 分治法
    什么是分治法分解-->解决-->合并归并排序#include<stdio.h>#include<math.h>//voidMerge(intA[],intp,intq,intr){ inti,j,k; intL[50],R[50]; intn1=q-p+1,n2=r-q; //为L和R数组赋值 for(i=0;i<n1;i++){ L[i]=A[p+i]......
  • F. Unique Occurrences(线段树分治+可撤销并查集)
    F.UniqueOccurrences假如我们删除所有权值为x的边,那么所有权值为x的边对答案的贡献就是\(\sumsz[u]*sz[v]\)sz表示两个联通块的大小,且(u,v)的边权为x我们可以用可撤销并查集来进行处理,简单来说就是将一条边的存在时间看作区间,然后挂到线段树上,然后遍历到每个叶子的时候进行......
  • 根号分治学习笔记
    根号分治的核心思想是平衡。板子题。很容易想到两种暴力:一是不做预处理,每次询问暴力查询,这样复杂度是\(\mathcalO(q\times\dfrac{n}{p})\)。二是预处理每个池子的值,每次\(\mathcalO(1)\)查询,复杂度为\(\mathcalO(np)\)。观察两个式子,由于\(q,n\)同阶,结合以下两种算法,......
  • 点分治
    第一场\(csp\)后的第一篇博客,我已经\(OIer\)大半年了,再也不是之前那个轻狂的小朋友了。。。所以考虑维护一种算法支持查询树上第\(k\)短的路径是否存在。首先构造两个函数\(\{dfsdist,dfssize\}\),当然其中\(dfssize\)主要是计算重心的。这两个函数相对比较好些,其......
  • 分治法
               ......