首页 > 其他分享 >虚树 学习笔记

虚树 学习笔记

时间:2023-07-14 20:23:46浏览次数:49  
标签:lc dep 笔记 学习 fa int 虚树 关键点

模板题

题目传送门
给定一棵树,每次给出 \(k\) 个点,断掉一些边,然后让这些给出的点和 \(1\) 号点不连通,求断边的边权和的最小值。
数据组数 \(T\le 5\cdot 10^5\),树的点数 \(n\le 2.5\cdot 10^5\),\(\sum k \le 5 \cdot 10^5\)

题目解析

我们发现每次给出的是一部分点,所以我们只需要考虑关键点,利用关键点建树跑个 DP 就好。
但是如果只考虑关键点的话,无法维护作为树的性质,所以我们还需要记录一些分叉点,就像图中一样。

如果 \(1,3,4\) 是关键点,那么为了维护树的形态 \(2\) 号点就也要加进去。
换句话说,所有关键点两两的 LCA (分叉点)都要加到虚树里面。
而由关键点和分叉点构成的这棵经过“路径压缩”的树就叫虚树。

虚树的构建

显然直接 \(O(n)\) 构建就不能很好利用虚树只存在较少关键点的性质,所以我们需要做到更快的构建方法。
首先我们按照所有的关键点按照 dfs 排序,然后只要取相邻两点的 LCA 即可。这样可以证明虚树的大小是 \(O(k)\) 的。
我们只需要用一个栈当维护右链(也就是还未加入虚树的点)就可以建出虚树。
每次考虑一个加入的新的一个点,考虑这个点和栈顶的 LCA,记做点 \(lc\)。

我们弹出栈里在 \(lc\) 下面的点,然后将这些点的边加入虚树中。
如果 \(lc\) 不在栈里面,然后让 \(lc\) 入栈。
最后让 \(x\) 入栈。这样复杂度就是 \(O(k\log k)\) 的了,瓶颈在于排序。

清空的时候需要 dfs 一次,不然直接全清空还是 \(O(n)\) 的。

#include<cmath>
#include<cstdio>
#include<iostream>
#include<algorithm>
#define db double
#define ll long long
#define Tp template<typename _T>
Tp _T mabs(_T a){ return a<0?-a:a; }
Tp _T mmax(_T a,_T b){ return a<b?b:a; }
Tp _T mmin(_T a,_T b){ return a<b?a:b; }
Tp void mswap(_T &a,_T &b){ _T t=a; a=b; b=t; return; }
struct IO{
    static const int S=1<<21;
    char buf[S],*p1,*p2;int st[105],Top;
    ~IO(){clear();}
    inline void clear(){fwrite(buf,1,Top,stdout);Top=0;}
    inline void pc(const char c){Top==S&&(clear(),0);buf[Top++]=c;}
    inline char gc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
    inline IO&operator >> (char&x){while(x=gc(),x==' '||x=='\n'||x=='\r');return *this;}
    template<typename T>inline IO&operator >> (T&x){
        x=0;bool f=0;char ch=gc();
        while(ch<'0'||ch>'9'){if(ch=='-') f^=1;ch=gc();}
        while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=gc();
        f?x=-x:0;return *this;
    }
    inline IO&operator << (const char c){pc(c);return *this;}
    template<typename T>inline IO&operator << (T x){
        if(x<0) pc('-'),x=-x;
        do{st[++st[0]]=x%10,x/=10;}while(x);
        while(st[0]) pc('0'+st[st[0]--]);return *this;
    }
}fin,fout;
#define maxn 250039
using namespace std;
int n,m,lgn,T,u,v,w;
struct Graph{
	int head[maxn],nex[maxn<<1],to[maxn<<1],c[maxn<<1],kkk;
	void _add(int x,int y,int z){ nex[++kkk]=head[x]; head[x]=kkk; to[kkk]=y; c[kkk]=z; return; }
	void add(int x,int y,int z){ _add(x,y,z); _add(y,x,z); return; }
}tr,vt;
int fa[maxn][20],minx[maxn][20],dep[maxn],dfn[maxn],d_cnt,h[maxn],st[maxn],top;
void dfs(int x,int pre){
	int i; dfn[x]=++d_cnt;
	for(i=tr.head[x];i;i=tr.nex[i]) if(tr.to[i]!=pre){
		dep[tr.to[i]]=dep[x]+1; fa[tr.to[i]][0]=x; minx[tr.to[i]][0]=tr.c[i]; dfs(tr.to[i],x);
	} return;
}
int lca(int x,int y){
	int i; if(dep[x]<dep[y]) mswap(x,y);
	for(i=lgn;i>=0;i--) if(dep[fa[x][i]]>=dep[y]) x=fa[x][i];
	for(i=lgn;i>=0;i--) if(fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];
	return x==y?x:fa[x][0];
}
void addedge(int x,int y){
	if(dep[x]<dep[y]) mswap(x,y);
	int i,sx=10000000,tx=x,ty=y;
	for(i=lgn;i>=0;i--) if(dep[fa[x][i]]>=dep[y]) sx=mmin(sx,minx[x][i]),x=fa[x][i];
	vt.add(tx,ty,sx); return;
}
int cmp(int x,int y){ return dfn[x]<dfn[y]; }
ll ans[maxn]; int flag[maxn];
void dp(int x,int pre){
	int i; ans[x]=0; //cerr<<"vis:"<<x<<" pre:"<<pre<<endl;
	for(i=vt.head[x];i;i=vt.nex[i]) if(vt.to[i]!=pre){
		dp(vt.to[i],x);
		if(!flag[vt.to[i]]) ans[x]+=mmin(ans[vt.to[i]],(ll)vt.c[i]);
		else ans[x]+=vt.c[i];
	} return;
}
void clean(int x,int pre){
	int i; for(i=vt.head[x];i;i=vt.nex[i]) if(vt.to[i]!=pre) clean(vt.to[i],x);
	vt.head[x]=0; flag[x]=0; return;
}
int main(){
	fin>>n; lgn=log2(n); int i,j,lc; for(i=1;i<n;i++){ fin>>u>>v>>w; tr.add(u,v,w); }
	dep[1]=1; dfs(1,-1);
	for(j=1;j<=lgn;j++) for(i=1;i<=n;i++)
		fa[i][j]=fa[fa[i][j-1]][j-1],minx[i][j]=mmin(minx[i][j-1],minx[fa[i][j-1]][j-1]);
	fin>>T; while(T--){
		fin>>m; for(i=1;i<=m;i++) fin>>h[i],flag[h[i]]=1; h[++m]=1,flag[1]=1;
		sort(h+1,h+m+1,cmp); st[top=1]=1;
		for(i=2;i<=m;i++){
			lc=lca(h[i],st[top]);
			while(dep[st[top]]>dep[lc]){
				if(dep[st[top-1]]<dep[lc]) addedge(st[top],lc);
				else addedge(st[top],st[top-1]); top--;
			} if(dep[st[top]]<dep[lc]) st[++top]=lc;
			st[++top]=h[i];
		}
		while(top>1) addedge(st[top],st[top-1]),top--;
		dp(1,-1); vt.kkk=0; clean(1,-1); fout<<ans[1]<<'\n';
	}
	return 0;
}

标签:lc,dep,笔记,学习,fa,int,虚树,关键点
From: https://www.cnblogs.com/jiangtaizhe001/p/17552057.html

相关文章

  • 学科知识图谱学习平台项目 :技术栈Java、Neo4j、MySQL等超详细教学
    学科知识图谱学习平台项目:技术栈Java、Neo4j、MySQL等超详细教学0.效果展示1.安装教程安装JavaSDK11,下载前需要登录Oracle账号,下载链接,安装教程,测试是否能在命令行工具调用javajava--versionjava17.0.12021-10-19LTSJava(TM)SERuntimeEnvironment(build......
  • Docker学习路线5:在 Docker 中实现数据持久化
    Docker可以运行隔离的容器,包括应用程序和其依赖项,与主机操作系统分离。默认情况下,容器是临时的,这意味着容器中存储的任何数据在终止后都将丢失。为了解决这个问题并在容器生命周期内保留数据,Docker提供了各种数据持久化方法。Docker卷绑定挂载Dockertmpfs挂载Docker卷......
  • 并查集笔记
    并查集导论并查集是一种数据结构,主要用于处理一些不相交集合的合并问题。一般应用在连通图、最小生成树、Kruskal算法、最近公共祖先(LCA)等算法中。举例用帮派例子理解并查集:在n个人中,分成了不同的帮派,每个帮派的人都互为朋友,朋友的朋友是朋友,例如1号和2号是朋友,1号和3号......
  • 【ChernoC++笔记】智能指针
    【44】【ChernoC++】【中字】C++的智能指针智能指针(Smartpointers)是C++中的一种特殊类型,用于管理动态分配的内存资源。智能指针通过封装指针,并在适当的时机自动释放内存,从而避免内存泄漏和悬空指针等常见问题。unique_ptr❓为什么叫做uniqueptr?unique_ptr不能复制:如果复......
  • 在美国留学学习php对就业帮助有多少
    PHP是一种广泛应用于网站编程和动态网页开发的脚本语言,拥有着强大的服务器端编程功能。对于许多计算机专业的学生来说,学习PHP并赴美留学,已经成为了一种趋势。毕业之后,他们常常想知道自己在美国就业的前景如何。留学网将从不同角度来论述PHP留学生在美国就业的前景。正文:一、专业认......
  • 【算法】并查集学习笔记
    1.并查集简介1.1什么是并查集并查集是一种用于管理元素所属集合的数据结构,实现为一个森林,其中每棵树表示一个集合,树中的节点表示对应集合中的元素。并查集支持两种操作:1.合并(merge):合并两个数所属的集合(合并两个树);2.查询(find):查询两个数是否在同一个集合中(查询两个数所对......
  • 机器学习之回归
    回归是机器学习中最常见的任务之一,回归(regression)问题预测的是一个连续值,而不是离散标签,比如根据气象数据预测明日气温,或者根据房地产数据估算房价(标量回归问题)。接下来就以回归问题最经典的波士顿房价为例,了解标量回归问题的基本配置。当然主要是对深度学习的训练与推理建立一个......
  • 鸟类识别系统python+TensorFlow+Django网页界面+卷积网络算法+深度学习模型
    一、介绍鸟类识别系统,使用Python作为主要开发语言,基于深度学习TensorFlow框架,搭建卷积神经网络算法。并通过对数据集进行训练,最后得到一个识别精度较高的模型。并基于Django框架,开发网页端操作平台,实现用户上传一张图片识别其名称。二、效果图片三、演示视频and代码视频+......
  • 零一PPT学习_P8/P31
    一、字体下载两个网站1、站长素材:Font.china2.com2、模板王:http://fonts.mobanwang.com/二、清除字体格式开始-字体-橡皮擦(清除字体格式) ......
  • 《可解释的机器学习》校对活动正式启动 | ApacheCN
    项目仓库:https://github.com/apachecn/interpretable-ml-book-zh整体进度:https://github.com/apachecn/interpretable-ml-book-zh/issues/1贡献指南:https://github.com/apachecn/interpretable-ml-book-zh/blob/master/CONTRIBUTING.md贡献指南请您勇敢地去翻译和改进翻译。虽然我......