当前位置: 首页 > article >正文

【图论】虚树 - 模板总结

适用于解决一棵树中只需要用到少部分点的时候,将需要用到的点提出来单独建一棵树

/********************* 虚树 *********************/
struct edge
{
	int to, next;
	int val;
};

struct Virtual_Tree
{
	int n; // 点数
	int dfn[N]; // dfs序
	int dep[N]; // 深度
	int fa[N][25], m[N];
	int num; // 关键点数
	vector<int> lst; // 关键点
	bool query[N]; // 是否为关键点
	int top, cnt1 = 1, cnt2 = 1, dfscnt = 1;
	int stk[MAXN];
	int head1[N], head2[N];
	struct edge edge1[N << 1], edge2[N << 1]; // 原树和虚树

	/* 在下方添加需要的信息定义 */
	int minv[N];
	/***************************/

	// 初始化
	void init()
	{
		for (int i = 1; i <= n; i ++ )
		{
			dfn[i] = dep[i] = m[i] = query[i] = 0;
			for (int j = 0; j < 24; j ++ ) fa[i][j] = 0;
		}
	}

	// 原树建边
	void add1(int x, int y, int v)
	{
		edge1[cnt1].next = head1[x];
    	edge1[cnt1].to = y;
    	edge1[cnt1].val = v;
    	head1[x] = cnt1 ++ ;
	}

	// 虚树建边
	void add2(int x, int y)
	{
    	edge2[cnt2].next = head2[x];
    	edge2[cnt2].to = y;
    	head2[x] = cnt2 ++ ;
	}

	// 预处理原树基本信息
	void dfs1(int pos)
	{
    	int k;
    	for (k = 0; fa[pos][k]; k ++ ) fa[pos][k + 1] = fa[fa[pos][k]][k];
    	m[pos] = k;
    	dfn[pos] = dfscnt++;
    	for (int i = head1[pos]; i; i = edge1[i].next)
    	{
    	    int to = edge1[i].to;
    	    if (!dfn[to])
    	    {
    	        dep[to] = dep[pos] + 1;
    	        fa[to][0] = pos;
				/* 在下方处理需要的信息 */
    	        minv[to] = min(minv[pos], edge1[i].val);
				/***********************/
    	        dfs1(to);
    	    }
    	}
	}

	// 倍增求lca
	int lca(int x, int y)
	{
    	if (dep[x] < dep[y]) swap(x, y);
		for (int i = m[x]; i > -1; i -- )
		{
    		if (dep[fa[x][i]] >= dep[y]) x = fa[x][i];
		}
    	if (x == y) return x;
		for (int i = m[x]; i > -1; i -- )
		{
    		if (fa[x][i] != fa[y][i])
    		{
    		    x = fa[x][i];
    		    y = fa[y][i];
    		}
		}
    	return fa[x][0];
	}

	// 建虚树 关键点存在lst里 lst大小为k 下标从0开始
	void build(int k, vector<int>& lst)
	{
		// 按照dfs序排序规则
		auto cmp = [&](int x1, int x2)
		{
			return dfn[x1] < dfn[x2];
		};
		sort(lst.begin(), lst.end(), cmp);
		stk[top = 1] = lst[0];
		for (int i = 1; i < k; i ++ )
		{
			int now = lst[i];
			int lc = lca(now, stk[top]);
			while (1)
			{
				if (dep[lc] >= dep[stk[top - 1]])
                {
                    if (lc != stk[top])
                    {
                        add2(lc, stk[top]);
                        if (lc != stk[top - 1]) stk[top] = lc;
                        else top -- ;
                    }
                    break;
                }
                else
                {
                    add2(stk[top - 1], stk[top]);
                    top -- ;
                }
			}
			stk[++ top] = now;
		}
		while (-- top) add2(stk[top], stk[top + 1]);
	}

	// 树形dp计算答案
	int dfs2(int u)
	{
		/* 下方填写计算答案代码逻辑 */

		/**************************/

		// 清空虚树
		query[u] = false;
		head2[u] = 0;
		return res;
	}

	// 在下方填写解题逻辑
	void solve()
	{
		/* 思路 */

		/********/

		// 每次建虚树后需要清空
		cnt2 = 1;
		lst.clear();
	}
} vtr;
/***********************************************/

http://www.kler.cn/a/301232.html

相关文章:

  • 机器学习day5-随机森林和线性代数1最小二乘法
  • 任务管理功能拆解——如何高效管理项目任务?
  • Stable Diffusion最全提示词写法教程
  • Siglus引擎 Unpack | 未完待续
  • 在MATLAB中导入TXT文件的若干方法
  • 如何在 Ubuntu 上安装 Jupyter Notebook
  • 2023Idea版本无法下载通义灵码插件以及无法登录问题
  • 828华为云征文 | Flexus X实例与华为云EulerOS的Tomcat安装指南
  • ELK在Linux上部署教程
  • RISC-V Non-MMU Linux学习笔记
  • 视频安防监控LntonAIServer安防管理平台抖动检测和过亮过暗检测
  • 机器学习与深度学习的区别
  • 生命周期函数
  • vue elementUI更改Checkbox 多选框禁用状态下文本颜色
  • AutoSar AP平台的SOMEIP文档的理解笔记
  • C++ priority_queue
  • 漫谈设计模式 [4]:原型模式
  • go-map系统学习
  • livox mid360不使用ros接收雷达数据
  • StreamPark集成k8s运行Flink
  • busybox移植:全能脚本版
  • 在亚马逊云科技上利用Graviton4代芯片构建高性能Java应用(下篇)
  • 3.Kubernetes资源对象之pod
  • 828华为云征文|华为云Flexus X实例docker部署最新版禅道构建属于自己的项目管理平台
  • 文心智能体应用:美国旅游助手的诞生
  • 【进展报告】9.9-9.12